ods: Working on DualArrayDeque.
This commit is contained in:
parent
d1abc22e0e
commit
b518212ba7
|
@ -57,3 +57,14 @@ resizing isn't too bad.
|
||||||
set/get in time O(1) time per operation, and add/remove in O(1+min(i, n-1))
|
set/get in time O(1) time per operation, and add/remove in O(1+min(i, n-1))
|
||||||
time per operation. Beginning with an empty ArrayDeque, performing any
|
time per operation. Beginning with an empty ArrayDeque, performing any
|
||||||
sequence of m operations results in a total of O(m) time resizing.
|
sequence of m operations results in a total of O(m) time resizing.
|
||||||
|
|
||||||
|
## Dual Array Deque
|
||||||
|
|
||||||
|
* Same performance bounds as ArrayDeque using a pair of ArrayStacks.
|
||||||
|
* While not better, it's instructive as an example of building a more complex
|
||||||
|
data structure from simpler ones.
|
||||||
|
* List is represented as a pair of ArrayStacks; these are fast when a
|
||||||
|
modification occurs at the end. The DAD uses two ArrayStacks called
|
||||||
|
front and back.
|
||||||
|
* front: list elements that are 0...front.size()-1
|
||||||
|
* back: same but reverse order
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include <ods/array_stack.h>
|
#include <ods/array_stack.h>
|
||||||
#include <ods/array_queue.h>
|
#include <ods/array_queue.h>
|
||||||
#include <ods/array_deque.h>
|
#include <ods/array_deque.h>
|
||||||
|
#include <ods/dual_array_deque.h>
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace ods;
|
using namespace ods;
|
||||||
|
|
||||||
|
@ -78,4 +79,34 @@ main(void)
|
||||||
ad.remove(3);
|
ad.remove(3);
|
||||||
ad.remove(4);
|
ad.remove(4);
|
||||||
cout << "size: " << ad.size() << ", cap: " << ad.cap() << endl;
|
cout << "size: " << ad.size() << ", cap: " << ad.cap() << endl;
|
||||||
|
|
||||||
|
cout << "=== DualArrayDeque ===" << endl;
|
||||||
|
DualArrayDeque<int> dad(1);
|
||||||
|
for (int i = 0; i < 5; i++) {
|
||||||
|
dad.add(0, 4-i);
|
||||||
|
}
|
||||||
|
cout << "size: " << dad.size() << ", cap: " << dad.cap() << endl;
|
||||||
|
|
||||||
|
for (int i = 0; i < 5; i++) {
|
||||||
|
dad.add(dad.size(), i);
|
||||||
|
}
|
||||||
|
cout << "size: " << dad.size() << ", cap: " << dad.cap() << endl;
|
||||||
|
|
||||||
|
for (int i = 0; i < dad.size(); i++) {
|
||||||
|
cout << i << "\t" << dad.get(i) << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
x = dad.remove(1);
|
||||||
|
assert(x == 1);
|
||||||
|
x = dad.remove(7);
|
||||||
|
assert(x == 3);
|
||||||
|
cout << "size: " << dad.size() << ", cap: " << dad.cap() << endl;
|
||||||
|
|
||||||
|
for (int i = 0; i < dad.size(); i++) {
|
||||||
|
cout << i << "\t" << dad.get(i) << endl;
|
||||||
|
}
|
||||||
|
dad.remove(2);
|
||||||
|
dad.remove(3);
|
||||||
|
dad.remove(4);
|
||||||
|
cout << "size: " << dad.size() << ", cap: " << dad.cap() << endl;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ template<typename T>
|
||||||
class ArrayStack {
|
class ArrayStack {
|
||||||
public:
|
public:
|
||||||
ArrayStack(int len) : n(0), a(Array<T>(len)) {}
|
ArrayStack(int len) : n(0), a(Array<T>(len)) {}
|
||||||
|
ArrayStack(Array<T> na, int len) : n(len), a(na) {}
|
||||||
int size(void) { return n; }
|
int size(void) { return n; }
|
||||||
int cap(void) { return a.length; }
|
int cap(void) { return a.length; }
|
||||||
T get(int i) { return a[i]; }
|
T get(int i) { return a[i]; }
|
||||||
|
|
|
@ -0,0 +1,91 @@
|
||||||
|
#ifndef __ODS_ODS_DUAL_ARRAY_DEQUE__
|
||||||
|
#define __ODS_ODS_DUAL_ARRAY_DEQUE__
|
||||||
|
|
||||||
|
#include <ods/array.h>
|
||||||
|
#include <ods/array_stack.h>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
namespace ods {
|
||||||
|
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
class DualArrayDeque {
|
||||||
|
public:
|
||||||
|
DualArrayDeque(int len) : front(ArrayStack<T>(len)), back(ArrayStack<T>(len)) {}
|
||||||
|
int size(void) { return front.size() + back.size(); }
|
||||||
|
int cap(void) { return front.cap() + back.cap(); }
|
||||||
|
T get(int i) {
|
||||||
|
if (i < front.size()) {
|
||||||
|
return front.get(front.size() - i - 1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return back.get(i - front.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
T set(int i, T x) {
|
||||||
|
if (i < front.size()) {
|
||||||
|
return front.set(front.size() - i - 1, x);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return back.set(i - front.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void add(int i, T x) {
|
||||||
|
if (i < front.size()) {
|
||||||
|
front.add(front.size() - i, x);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
back.add(i - front.size(), x);
|
||||||
|
}
|
||||||
|
balance();
|
||||||
|
}
|
||||||
|
|
||||||
|
T remove(int i) {
|
||||||
|
T x;
|
||||||
|
if (i < front.size()) {
|
||||||
|
x = front.remove(front.size() - i - 1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
x = back.remove(i - front.size());
|
||||||
|
}
|
||||||
|
balance();
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
ArrayStack<T> front;
|
||||||
|
ArrayStack<T> back;
|
||||||
|
|
||||||
|
static inline int max(int x, int y) {
|
||||||
|
return x > y ? x : y;
|
||||||
|
}
|
||||||
|
|
||||||
|
void balance(void) {
|
||||||
|
if ((3 * front.size() < back.size()) ||
|
||||||
|
(3 * back.size() < front.size())) {
|
||||||
|
std::cerr << "rebalancing\n";
|
||||||
|
auto n = front.size();
|
||||||
|
auto nf = n / 2;
|
||||||
|
Array<T> af(max(2*nf, 1));
|
||||||
|
for (int i = 0; i < nf; i++) {
|
||||||
|
af[nf-i-1] = this->get(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto nb = n - nf;
|
||||||
|
Array<T> ab(max(2*nb, 1));
|
||||||
|
for (int i = 0; i < nb; i++) {
|
||||||
|
ab[i] = this->get(nf+i);
|
||||||
|
}
|
||||||
|
|
||||||
|
ArrayStack<T> fas(af, nf);
|
||||||
|
ArrayStack<T> bas(ab, nb);
|
||||||
|
this->front = fas;
|
||||||
|
this->back = bas;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace ods
|
||||||
|
|
||||||
|
#endif // __ODS_ODS_DUAL_ARRAY_DEQUE__
|
Loading…
Reference in New Issue