Finish ArrayDeque.
This commit is contained in:
parent
6311eaf378
commit
6d1ad44409
|
@ -28,6 +28,32 @@ resizing isn't too bad.
|
||||||
* The analysis of add and remove didn't consider cost of resize.
|
* The analysis of add and remove didn't consider cost of resize.
|
||||||
* An amortised analysis is done instead that considers the cost of all calls
|
* An amortised analysis is done instead that considers the cost of all calls
|
||||||
to add and remove, given a sequence of *m* calls to either.
|
to add and remove, given a sequence of *m* calls to either.
|
||||||
* Lemma: if an empty ArrayStack is created and any sequence of *m* >= 1 calls
|
* **Lemma**: if an empty ArrayStack is created and any sequence of *m* >= 1
|
||||||
to add and remove are performed, the total time spent in calls to resize is
|
calls to add and remove are performed, the total time spent in calls to
|
||||||
O(m).
|
resize is O(m).
|
||||||
|
* Optimisations (FastArrayStack): using memcpy or std::copy to copy blocks of
|
||||||
|
data, not one element at a time.
|
||||||
|
|
||||||
|
## ArrayQueue
|
||||||
|
|
||||||
|
* ArrayStack is a bad implementation for a FIFO queue; either add or remove
|
||||||
|
must work from the head with index = 0, which means all calls to that
|
||||||
|
method will result in running time of O(n).
|
||||||
|
* We could do this with an infinite array, using an index into the head (*j*)
|
||||||
|
and the size of the backing array. We don't have an infinite array, so we'll
|
||||||
|
have to use modular arithmetic with a finite stack.
|
||||||
|
* **Theorem**: Ignoring the cost of calls to resize, an ArrayQueue supports the
|
||||||
|
operations add and remove in O(1) per operation. Beginning with an empty
|
||||||
|
ArrayQueue, any sequence of m add/remove operations will result in a total
|
||||||
|
of O(m) time resizing.
|
||||||
|
|
||||||
|
## ArrayDeque
|
||||||
|
|
||||||
|
* Implementation of adding and removing from both ends using the same circular
|
||||||
|
buffer technique.
|
||||||
|
* add/remove check whether their index is before or after the halfway point and
|
||||||
|
shift from there as a performance benefit.
|
||||||
|
* **Theorem**: Ignoring the cost of calls to resize, an ArrayDeque supports
|
||||||
|
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.
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
#include <cassert>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <ods/array.h>
|
#include <ods/array.h>
|
||||||
#include <ods/array_stack.h>
|
#include <ods/array_stack.h>
|
||||||
|
@ -51,16 +52,30 @@ main(void)
|
||||||
cout << "=== ArrayDeque ===" << endl;
|
cout << "=== ArrayDeque ===" << endl;
|
||||||
ArrayDeque<int> ad(1);
|
ArrayDeque<int> ad(1);
|
||||||
for (int i = 0; i < 5; i++) {
|
for (int i = 0; i < 5; i++) {
|
||||||
ad.add(0, i);
|
ad.add(0, 4-i);
|
||||||
}
|
}
|
||||||
cout << "size: " << ad.size() << ", cap: " << ad.cap() << endl;
|
cout << "size: " << ad.size() << ", cap: " << ad.cap() << endl;
|
||||||
|
|
||||||
for (int i = 0; i < 5; i++) {
|
for (int i = 0; i < 5; i++) {
|
||||||
ad.add(ad.size() - 1, i);
|
ad.add(ad.size(), i);
|
||||||
}
|
}
|
||||||
cout << "size: " << ad.size() << ", cap: " << ad.cap() << endl;
|
cout << "size: " << ad.size() << ", cap: " << ad.cap() << endl;
|
||||||
|
|
||||||
for (int i = 0; i < ad.size(); i++) {
|
for (int i = 0; i < ad.size(); i++) {
|
||||||
cout << i << "\t" << ad.get(i) << endl;
|
cout << i << "\t" << ad.get(i) << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto x = ad.remove(1);
|
||||||
|
assert(x == 1);
|
||||||
|
x = ad.remove(7);
|
||||||
|
assert(x == 3);
|
||||||
|
cout << "size: " << ad.size() << ", cap: " << ad.cap() << endl;
|
||||||
|
|
||||||
|
for (int i = 0; i < ad.size(); i++) {
|
||||||
|
cout << i << "\t" << ad.get(i) << endl;
|
||||||
|
}
|
||||||
|
ad.remove(2);
|
||||||
|
ad.remove(3);
|
||||||
|
ad.remove(4);
|
||||||
|
cout << "size: " << ad.size() << ", cap: " << ad.cap() << endl;
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,6 +55,28 @@ public:
|
||||||
n++;
|
n++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
T remove(int i) {
|
||||||
|
T x = a[index(i)];
|
||||||
|
if (i < (n/2)) {
|
||||||
|
for (int k = i; k > 0; k--) {
|
||||||
|
a[index(k)] = a[index(k-1)];
|
||||||
|
}
|
||||||
|
j = index(1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (int k = i; k < n-1; k++) {
|
||||||
|
a[index(k)] = a[index(k+1)];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
n--;
|
||||||
|
|
||||||
|
if (a.length > 3 * n) {
|
||||||
|
resize();
|
||||||
|
}
|
||||||
|
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
void resize(void) {
|
void resize(void) {
|
||||||
Array<T> b(max(2 * n, 1));
|
Array<T> b(max(2 * n, 1));
|
||||||
for (int k = 0; k < n; k++) {
|
for (int k = 0; k < n; k++) {
|
||||||
|
|
Loading…
Reference in New Issue