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))
|
||||
time per operation. Beginning with an empty ArrayDeque, performing any
|
||||
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_queue.h>
|
||||
#include <ods/array_deque.h>
|
||||
#include <ods/dual_array_deque.h>
|
||||
using namespace std;
|
||||
using namespace ods;
|
||||
|
||||
|
@ -78,4 +79,34 @@ main(void)
|
|||
ad.remove(3);
|
||||
ad.remove(4);
|
||||
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 {
|
||||
public:
|
||||
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 cap(void) { return a.length; }
|
||||
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