ods: Working on DualArrayDeque.

This commit is contained in:
Kyle Isom 2018-03-05 15:54:44 -08:00
parent d1abc22e0e
commit b518212ba7
4 changed files with 134 additions and 0 deletions

View File

@ -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

View File

@ -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;
}

View File

@ -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]; }

View File

@ -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__