diff --git a/artigos/another-persistence.pdf b/artigos/another-persistence.pdf new file mode 100644 index 0000000..74dad0d Binary files /dev/null and b/artigos/another-persistence.pdf differ diff --git a/artigos/jacm-final.pdf b/artigos/jacm-final.pdf new file mode 100644 index 0000000..a9cde23 Binary files /dev/null and b/artigos/jacm-final.pdf differ diff --git a/code/a.exe b/code/a.exe new file mode 100644 index 0000000..3a92cae Binary files /dev/null and b/code/a.exe differ diff --git a/code/aux1.cpp b/code/aux1.cpp new file mode 100644 index 0000000..e71b491 --- /dev/null +++ b/code/aux1.cpp @@ -0,0 +1,40 @@ +#include +#include +#include +#define MAXN 10 + +int pascal[MAXN][MAXN], N[MAXN][MAXN]; + +int main() { + for(int n = 0; n < MAXN; n++) { + for(int k = 0; k < MAXN; k++) { + if (k > n) pascal[n][k] = 0; + else if (k == n || k == 0) pascal[n][k] = 1; + else pascal[n][k] = pascal[n-1][k-1] + pascal[n-1][k]; + if (pascal[n][k]) printf("%4d ", pascal[n][k]); + } + printf("\n"); + } + memset(&N, 0, sizeof N); + N[0][0] = 1; + for(int t = 0; t+1 < MAXN; t++) { + for(int i = 0; i <= t; i++) { + if (i > 0) { + N[t+1][i+1] += N[t][i]; + N[t+1][i-1] += N[t][i]; + } + else N[t+1][i+1] += 2*N[t][i]; + assert((i+t)%2 == 0 || N[t][i] == 0); + int p; + if ((i+t)%2 != 0) p = 0; + else { + int n = t; + int k = (i+t)/2; + p = (i == 0 ? 1 : 2)*pascal[n][k]; + } + printf("%4d,%4d ", N[t][i], p); + } + printf("\n"); + } + return 0; +} \ No newline at end of file diff --git a/code/pdeque.cpp b/code/pdeque.cpp new file mode 100644 index 0000000..4c9f8e1 --- /dev/null +++ b/code/pdeque.cpp @@ -0,0 +1,776 @@ +#include +#include + +/* + * Normal linked list deque + */ + +struct Node { + const int data; + Node *nxt, *prv; + Node(Node *_nxt, Node *_prv, int _data) : + nxt(_nxt), prv(_prv), data(_data) { } +}; + +class Deque { +private: + Node *front, *back; + int size; +public: + Deque() : + front(NULL), back(NULL), size(0) {} + ~Deque() { Clear(); } + void Clear() { + Node *aux; + while(front != NULL) { + aux = front; + front = front->nxt; + delete aux; + } + back = NULL; + size = 0; + } + int Front() { + return front->data; + } + int Back() { + return back->data; + } + void PopFront() { + Node *aux = front; + front = front->nxt; + delete aux; + if (front == NULL) back = NULL; + else front->prv = NULL; + size--; + } + void PopBack() { + Node *aux = back; + back = back->prv; + delete aux; + if (back == NULL) front = NULL; + else back->nxt = NULL; + size--; + } + void PushBack(int data) { + if (back != NULL) back = back->nxt = new Node(NULL, back, data); + else front = back = new Node(NULL, NULL, data); + size++; + } + void PushFront(int data) { + if (front != NULL) front = front->prv = new Node(front, NULL, data); + else front = back = new Node(NULL, NULL, data); + size++; + } + int Size() { + return size; + } + bool Empty() { + return size == 0; + } +}; + +/* + * Persistent linked list deque with fat node method + */ + +#include + +struct FNode { + std::map data; + std::map nxt, prv; + FNode(FNode *_nxt, FNode *_prv, int _data, int i) { + nxt[i] = _nxt; + prv[i] = _prv; + data[i] = _data; + } + FNode* GetNxt(int ver) { + return (--nxt.upper_bound(ver))->second; + } + FNode* GetPrv(int ver) { + return (--prv.upper_bound(ver))->second; + } + int GetData(int ver) { + return (--data.upper_bound(ver))->second; + } +}; + +class FatDeque { +private: + std::vector front, back, nodes; + std::vector size; +public: + FatDeque() { + front.push_back(NULL); + back.push_back(NULL); + size.push_back(0); + } + ~FatDeque() { Clear(); } + void Clear() { + for(int i = 0; i < (int)nodes.size(); i++) { + delete nodes[i]; + } + back.clear(); back.push_back(NULL); + front.clear(); front.push_back(NULL); + size.clear(); size.push_back(0); + nodes.clear(); + } + int Front(int ver) { + return front[ver]->GetData(ver); + } + int Back(int ver) { + return back[ver]->GetData(ver); + } + void PopFront() { + int ver = LatestVersion(); + front.push_back(front[ver]->GetNxt(ver)); + if (front.back() == NULL) back.push_back(NULL); + else { + front.back()->prv[ver+1] = NULL; + back.push_back(back[ver]); + } + size.push_back(size[ver]-1); + } + void PopBack() { + int ver = LatestVersion(); + back.push_back(back[ver]->GetPrv(ver)); + if (back.back() == NULL) front.push_back(NULL); + else { + back.back()->nxt[ver+1] = NULL; + front.push_back(front[ver]); + } + size.push_back(size[ver]-1); + } + void PushBack(int data) { + int ver = LatestVersion(); + if (back[ver] != NULL) { + FNode *newNode = new FNode(NULL, back[ver], data, ver+1); + nodes.push_back(newNode); + back[ver]->nxt[ver+1] = newNode; + back.push_back(newNode); + front.push_back(front[ver]); + } + else { + FNode *newNode = new FNode(NULL, NULL, data, ver+1); + back.push_back(newNode); + front.push_back(newNode); + nodes.push_back(newNode); + } + size.push_back(size[ver]+1); + } + void PushFront(int data) { + int ver = LatestVersion(); + if (front[ver] != NULL){ + FNode *newNode = new FNode(front[ver], NULL, data, ver+1); + nodes.push_back(newNode); + front[ver]->prv[ver+1] = newNode; + front.push_back(newNode); + back.push_back(back[ver]); + } + else { + FNode *newNode = new FNode(NULL, NULL, data, ver+1); + back.push_back(newNode); + front.push_back(newNode); + nodes.push_back(newNode); + } + size.push_back(size[ver]+1); + } + int Size(int ver) { + return size[ver]; + } + bool Empty(int ver) { + return size[ver] == 0; + } + int LatestVersion() { + return int(size.size()) - 1; + } +}; + +/* + * Persistent linked list deque with node copy + */ + +struct CNode; + +struct Leader { + CNode *recent; + Leader(CNode *_recent) : recent(_recent) { } +}; + +struct CNode { + Leader *leader; + int timestamp; + const int data; + CNode *nxt, *prv; + CNode(CNode *_nxt, CNode *_prv, int _data, int i, bool newLeader = true) : + nxt(_nxt), prv(_prv), data(_data), timestamp(i) { + if (newLeader) leader = new Leader(this); + else leader = NULL; + } + ~CNode() { + if (leader->recent == this) delete leader; + } + CNode *GetRecent() { + return leader->recent; + } + CNode *Copy(int i) { + if (this != leader->recent) + return leader->recent->Copy(i); + CNode *copy = new CNode(nxt, prv, data, i, false); + copy->leader = leader; + leader->recent = copy; + return copy; + } +}; + +class CopyDeque { +private: + std::vector front, back, nodes; + std::vector size; +public: + CopyDeque() { + front.push_back(NULL); + back.push_back(NULL); + size.push_back(0); + } + ~CopyDeque() { Clear(); } + void Clear() { + for(int i = 0; i < (int)nodes.size(); i++) { + delete nodes[i]; + } + back.clear(); back.push_back(NULL); + front.clear(); front.push_back(NULL); + size.clear(); size.push_back(0); + nodes.clear(); + } + int Front(int ver) { + return front[ver]->data; + } + int Back(int ver) { + return back[ver]->data; + } + void PopFront() { + int i = LatestVersion(); + CNode *newFront = front[i]->GetRecent()->nxt; + if (newFront != NULL) { + newFront = newFront->Copy(i+1); + newFront->prv = NULL; + } + front.push_back(newFront); + if (newFront == NULL) back.push_back(NULL); + else back.push_back(back[i]->GetRecent()); + size.push_back(size[i]-1); + } + void PopBack() { + int i = LatestVersion(); + CNode *newBack = back[i]->GetRecent()->prv; + if (newBack != NULL) { + newBack = newBack->Copy(i+1); + newBack->nxt = NULL; + } + back.push_back(newBack); + if (newBack == NULL) front.push_back(NULL); + else front.push_back(front[i]->GetRecent()); + size.push_back(size[i]-1); + } + void PushBack(int data) { + int i = LatestVersion(); + if (back[i] == NULL) { + CNode *newNode = new CNode(NULL, NULL, data, i+1); + nodes.push_back(newNode); + front.push_back(newNode); + back.push_back(newNode); + } + else { + CNode *copyBack = back[i]->Copy(i+1); + CNode *newNode = new CNode(NULL, copyBack, data, i+1); + nodes.push_back(newNode); + copyBack->nxt = newNode; + front.push_back(front[i]->GetRecent()); + back.push_back(newNode); + } + size.push_back(size[i]+1); + } + void PushFront(int data) { + int i = LatestVersion(); + if (front[i] == NULL) { + CNode *newNode = new CNode(NULL, NULL, data, i+1); + nodes.push_back(newNode); + front.push_back(newNode); + back.push_back(newNode); + } + else { + CNode *copyFront = front[i]->Copy(i+1); + CNode *newNode = new CNode(copyFront, NULL, data, i+1); + nodes.push_back(newNode); + copyFront->prv = newNode; + back.push_back(back[i]->GetRecent()); + front.push_back(newNode); + } + size.push_back(size[i]+1); + } + int Size(int ver) { + return size[ver]; + } + bool Empty(int ver) { + return size[ver] == 0; + } + int LatestVersion() { + return int(back.size())-1; + } +}; + +/* + * Persistent linked list deque with LA and LCA + */ + +struct PNode { + const int data, depth; + std::vector par; + PNode(int _data, int _depth) : + data(_data), depth(_depth) { } +}; + +class PersistentDeque { +private: + std::vector front, back; + std::vector nodes; + PNode *Newnode(PNode *parent, int data) { + PNode *node; + if (parent != NULL) { + node = new PNode(data, parent->depth + 1); + node->par.push_back(parent); + for(int i = 1; i-1 < (int)node->par[i-1]->par.size(); i++) { + node->par.push_back(node->par[i-1]->par[i-1]); + } + } + else node = new PNode(data, 1); + nodes.push_back(node); + return node; + } + PNode *LowestCommonAncestor(PNode *u, PNode *v) { + if (u == NULL || v == NULL) return NULL; + u = LevelAncestor(u, u->depth - v->depth); + v = LevelAncestor(v, v->depth - u->depth); + if (u == v) return u; + for(int i = int(u->par.size()) - 1; i>= 0; i--) { + while(i < (int)u->par.size() && u->par[i] != v->par[i]) { + u = u->par[i]; + v = v->par[i]; + } + } + return u->par[0]; + } + PNode *LevelAncestor(PNode *node, int jump) { + if (node == NULL || jump <= 0) return node; + for(int i = 0; i < (int)node->par.size(); i++) { + if (jump & (1<par[i]; + } + } + return node; + } +public: + PersistentDeque() { Clear(); } + ~PersistentDeque() { Clear(); } + void Clear() { + for(int i = 0; i < (int)nodes.size(); i++) { + delete nodes[i]; + } + nodes.clear(); + back.clear(); back.push_back(NULL); + front.clear(); front.push_back(NULL); + } + int Front(int ver) { + return front[ver]->data; + } + int Back(int ver) { + return back[ver]->data; + } + int PopFront(int ver) { + if (front[ver] == back[ver]) { + back.push_back(NULL); + front.push_back(NULL); + return int(front.size())-1; + } + PNode *lca = LowestCommonAncestor(front[ver], back[ver]); + back.push_back(back[ver]); + if (front[ver] == lca) { + PNode *la = LevelAncestor(back[ver], back[ver]->depth - lca->depth - 1); + front.push_back(la); + } + else front.push_back(front[ver]->par[0]); + return int(front.size())-1; + } + int PopBack(int ver) { + if (front[ver] == back[ver]) { + back.push_back(NULL); + front.push_back(NULL); + return int(back.size())-1; + } + PNode *lca = LowestCommonAncestor(front[ver], back[ver]); + front.push_back(front[ver]); + if (back[ver] == lca) { + PNode *la = LevelAncestor(front[ver], front[ver]->depth - lca->depth - 1); + back.push_back(la); + } + else back.push_back(back[ver]->par[0]); + return int(back.size())-1; + } + int PushFront(int ver, int data) { + PNode *node = Newnode(front[ver], data); + front.push_back(node); + if (back[ver] == NULL) back.push_back(node); + else back.push_back(back[ver]); + return int(front.size()) - 1; + } + int PushBack(int ver, int data) { + PNode *node = Newnode(back[ver], data); + back.push_back(node); + if (front[ver] == NULL) front.push_back(node); + else front.push_back(front[ver]); + return int(back.size()) - 1; + } + int At(int ver, int i) { + PNode *lca = LowestCommonAncestor(front[ver], back[ver]); + int frontDist = front[ver]->depth - lca->depth; + int backDist = back[ver]->depth - lca->depth; + PNode *node; + if (i <= frontDist) node = LevelAncestor(front[ver], i); + else node = LevelAncestor(back[ver], frontDist + backDist - i); + return node->data; + } + int Size(int ver) { + PNode *lca = LowestCommonAncestor(front[ver], back[ver]); + if (lca == NULL) return 0; + return front[ver]->depth + back[ver]->depth - 2*lca->depth + 1; + } + bool Empty(int ver) { + return Size(ver) == 0; + } + int LatestVersion() { + return int(back.size())-1; + } +}; + +/* + * Unit tests + */ + +#include +#include +#include +#define NTESTS 10000 +#define RANGE 1000 + +bool TestNormalDeque(bool push) { + srand(time(NULL)); + std::deque control; + Deque deq; + for(int test = 1; test <= NTESTS || !control.empty(); test++) { + int add = push ? 1 : rand()%2; + int front = rand()%2; + if (add && test <= NTESTS) { + int data = rand()%RANGE; + if (front) { + control.push_front(data); + deq.PushFront(data); + } + else { + control.push_back(data); + deq.PushBack(data); + } + } + else { + if (control.empty()) { + test--; + continue; + } + if (front) { + control.pop_front(); + deq.PopFront(); + } + else { + control.pop_back(); + deq.PopBack(); + } + } + if (control.size() != deq.Size()) { + printf("failed on size test %d\n", test); + return false; + } + if (!control.empty()) { + int data1 = control.front(); + int data2 = deq.Front(); + if (data1 != data2) { + printf("failed on front test %d: %d-%d\n", test, data1, data2); + return false; + } + data1 = control.back(); + data2 = deq.Back(); + if (data1 != data2) { + printf("failed on back test %d: %d-%d\n", test, data1, data2); + return false; + } + } + } + printf("All normal deque tests passed\n"); + return true; +} + +bool TestPersistentDequeCorrectness(int suits, bool total, bool push = false) { + srand(time(NULL)); + for(int suit = 0; suit < suits; suit++) { + std::deque control[NTESTS]; + PersistentDeque deq; + FatDeque fdeq; + CopyDeque cdeq; + for(int test = 1; test < NTESTS; test++) { + int add = push ? 1 : rand()%2; + int front = rand()%2; + int ver = total ? rand()%test : test-1; + control[test] = control[ver]; + if (add || control[test].empty()) { + int data = rand()%RANGE; + if (front) { + control[test].push_front(data); + deq.PushFront(ver, data); + if (!total) { + fdeq.PushFront(data); + cdeq.PushFront(data); + } + } + else { + control[test].push_back(data); + deq.PushBack(ver, data); + if (!total) { + fdeq.PushBack(data); + cdeq.PushBack(data); + } + } + } + else { + if (front) { + control[test].pop_front(); + deq.PopFront(ver); + if (!total) { + fdeq.PopFront(); + cdeq.PopFront(); + } + } + else { + control[test].pop_back(); + deq.PopBack(ver); + if (!total) { + fdeq.PopBack(); + cdeq.PopBack(); + } + } + } + } + for(int test = 0; test < NTESTS; test++) { + if (control[test].size() != deq.Size(test)) { + printf("failed on size test %d\n", test); + return false; + } + if (!control[test].empty()) { + int data1 = control[test].front(); + int data2 = deq.Front(test); + int data3 = total ? data1 : fdeq.Front(test); + int data4 = total ? data1 : cdeq.Front(test); + if (data1 != data2) { + printf("lca deque failed on front test %d: %d-%d\n", test, data1, data2); + return false; + } + if (data1 != data3) { + printf("fat deque failed on front test %d: %d-%d\n", test, data1, data2); + return false; + } + if (data1 != data4) { + printf("copy deque failed on front test %d: %d-%d\n", test, data1, data2); + return false; + } + data1 = control[test].back(); + data2 = deq.Back(test); + data3 = total ? data1 : fdeq.Back(test); + data4 = total ? data1 : cdeq.Back(test); + if (data1 != data2) { + printf("lca deque failed on back test %d: %d-%d\n", test, data1, data2); + return false; + } + if (data1 != data3) { + printf("dat deque failed on back test %d: %d-%d\n", test, data1, data2); + return false; + } + if (data1 != data4) { + printf("copy deque failed on back test %d: %d-%d\n", test, data1, data2); + return false; + } + } + for(int at = 0; !control[test].empty() && at < 10; at++) { + int i = rand()%control[test].size(); + int data1 = control[test][i]; + int data2 = deq.At(test, i); + if (data1 != data2) { + printf("failed on at %d test %d: %d-%d\n", i, test, data1, data2); + return false; + } + } + } + } + printf("All %s persistent deque tests passed, %s\n", + total ? "total" : "partial", + push ? "push only" : "push and pop" + ); + return true; +} + + +bool TestPersistentDequeTime(int suits, bool total, bool push = false) { + long long seed = time(NULL); + srand(seed); + clock_t t = clock(); //control + for(int suit = 0; suit < suits; suit++) { + std::deque control[NTESTS]; + for(int test = 1; test < NTESTS; test++) { + int add = push ? 1 : rand()%2; + int front = rand()%2; + int ver = total ? rand()%test : test-1; + control[test] = control[ver]; + if (add || control[test].empty()) { + int data = rand()%RANGE; + if (front) control[test].push_front(data); + else control[test].push_back(data); + } + else { + if (front) control[test].pop_front(); + else control[test].pop_back(); + } + } + for(int test = 0; test < NTESTS; test++) { + control[test].size(); + if (!control[test].empty()) { + control[test].front(); + control[test].back(); + } + } + } + t = clock() - t; + printf("%s persistent control deque time, %s: %.0f us\n", + total ? "Total" : "Partial", + push ? "push only" : "push and pop", + t*1000000.0/CLOCKS_PER_SEC/suits + ); + srand(seed); + t = clock(); //lca + for(int suit = 0; suit < suits; suit++) { + PersistentDeque deq; + for(int test = 1; test < NTESTS; test++) { + int add = push ? 1 : rand()%2; + int front = rand()%2; + int ver = total ? rand()%test : test-1; + if (add || deq.Empty(ver)) { + int data = rand()%RANGE; + if (front) deq.PushFront(ver, data); + else deq.PushBack(ver, data); + } + else { + if (front) deq.PopFront(ver); + else deq.PopBack(ver); + } + } + for(int test = 0; test < NTESTS; test++) { + deq.Size(test); + if (!deq.Empty(test)) { + deq.Front(test); + deq.Back(test); + } + } + } + t = clock() - t; + printf("%s persistent LCA deque time, %s: %.0f us\n", + total ? "Total" : "Partial", + push ? "push only" : "push and pop", + t*1000000.0/CLOCKS_PER_SEC/suits + ); + if (total) return true; + srand(seed); + t = clock(); //fat + for(int suit = 0; suit < suits; suit++) { + FatDeque deq; + for(int test = 1; test < NTESTS; test++) { + int add = push ? 1 : rand()%2; + int front = rand()%2; + int ver = total ? rand()%test : test-1; + if (add || deq.Empty(ver)) { + int data = rand()%RANGE; + if (front) deq.PushFront(data); + else deq.PushBack(data); + } + else { + if (front) deq.PopFront(); + else deq.PopBack(); + } + } + for(int test = 0; test < NTESTS; test++) { + deq.Size(test); + if (!deq.Empty(test)) { + deq.Front(test); + deq.Back(test); + } + } + } + t = clock() - t; + printf("%s persistent fat deque time, %s: %.0f us\n", + total ? "Total" : "Partial", + push ? "push only" : "push and pop", + t*1000000.0/CLOCKS_PER_SEC/suits + ); + srand(seed); + t = clock(); //copy + for(int suit = 0; suit < suits; suit++) { + CopyDeque deq; + for(int test = 1; test < NTESTS; test++) { + int add = push ? 1 : rand()%2; + int front = rand()%2; + int ver = total ? rand()%test : test-1; + if (add || deq.Empty(ver)) { + int data = rand()%RANGE; + if (front) deq.PushFront(data); + else deq.PushBack(data); + } + else { + if (front) deq.PopFront(); + else deq.PopBack(); + } + } + for(int test = 0; test < NTESTS; test++) { + deq.Size(test); + if (!deq.Empty(test)) { + deq.Front(test); + deq.Back(test); + } + } + } + t = clock() - t; + printf("%s persistent copy deque time, %s: %.0f us\n", + total ? "Total" : "Partial", + push ? "push only" : "push and pop", + t*1000000.0/CLOCKS_PER_SEC/suits + ); + return true; +} + +int main() { + TestNormalDeque(false); + TestPersistentDequeCorrectness(100, false, false); + TestPersistentDequeCorrectness(100, true, false); + TestPersistentDequeTime(100, false, false); + TestPersistentDequeTime(100, true, false); + TestNormalDeque(true); + TestPersistentDequeCorrectness(100, false, true); + TestPersistentDequeCorrectness(100, true, true); + TestPersistentDequeTime(100, false, true); + TestPersistentDequeTime(100, true, true); + return 0; +} \ No newline at end of file diff --git a/pheap.cpp b/code/pheap.cpp similarity index 100% rename from pheap.cpp rename to code/pheap.cpp diff --git a/pitreap.cpp b/code/pitreap.cpp similarity index 100% rename from pitreap.cpp rename to code/pitreap.cpp diff --git a/code/pqueue.cpp b/code/pqueue.cpp new file mode 100644 index 0000000..bd87dbd --- /dev/null +++ b/code/pqueue.cpp @@ -0,0 +1,637 @@ +#include +#include + +/* + * Normal linked list queue + */ + +struct Node { + const int data; + Node *nxt; + Node(Node *_nxt, int _data) : + nxt(_nxt), data(_data) { } +}; + +class Queue { +private: + Node *front, *back; + int size; +public: + Queue() : + front(NULL), back(NULL), size(0) {} + ~Queue() { Clear(); } + void Clear() { + while(front != NULL) { + Node *aux = front; + front = front->nxt; + delete aux; + } + back = NULL; + size = 0; + } + int Front() { + return front->data; + } + void Pop() { + Node *prv = front; + front = front->nxt; + delete prv; + size--; + if (front == NULL) back = NULL; + } + void Push(int data) { + if (front != NULL) back = back->nxt = new Node(NULL, data); + else front = back = new Node(NULL, data); + size++; + } + int Size() { + return size; + } + bool Empty() { + return size == 0; + } +}; + +/* + * Persistent linked list queue with fat node method + */ + +#include + +struct FNode { + std::map data; + std::map nxt; + FNode(FNode *_nxt, int _data, int i) { + data[i] = _data; + nxt[i] = _nxt; + } + FNode* GetNxt(int ver) { + return (--nxt.upper_bound(ver))->second; + } + int GetData(int ver) { + return (--data.upper_bound(ver))->second; + } +}; + +class FatQueue { +private: + std::vector front, back, nodes; + std::vector size; +public: + FatQueue() { + front.push_back(NULL); + back.push_back(NULL); + size.push_back(0); + } + ~FatQueue() { Clear(); } + void Clear() { + for(int i = 0; i < (int)nodes.size(); i++) { + delete nodes[i]; + } + back.clear(); back.push_back(NULL); + front.clear(); front.push_back(NULL); + size.clear(); size.push_back(0); + nodes.clear(); + } + int Front(int ver) { + return front[ver]->GetData(ver); + } + void Pop() { + int i = LatestVersion(); + front.push_back(front[i]->GetNxt(i)); + if (front.back() == NULL) back.push_back(NULL); + else back.push_back(back[i]); + size.push_back(size[i]-1); + } + void Push(int data) { + int i = LatestVersion(); + FNode *newNode = new FNode(NULL, data, i+1); + nodes.push_back(newNode); + if (front[i] != NULL) { + back[i]->nxt[i+1] = newNode; + front.push_back(front[i]); + } + else front.push_back(newNode); + back.push_back(newNode); + size.push_back(size[i]+1); + } + int Size(int ver) { + return size[ver]; + } + bool Empty(int ver) { + return size[ver] == 0; + } + int LatestVersion() { + return int(back.size())-1; + } +}; + +/* + * Persistent linked list queue with node copy + */ +struct CNode; + +struct Leader { + CNode *recent; + Leader(CNode *_recent) : recent(_recent) { } +}; + +struct CNode { + Leader *leader; + int timestamp; + const int data; + CNode *nxt; + CNode(CNode *_nxt, int _data, int i, bool newLeader = true) : + nxt(_nxt), data(_data), timestamp(i) { + if (newLeader) leader = new Leader(this); + else leader = NULL; + } + ~CNode() { + if (leader->recent == this) delete leader; + } + CNode *GetRecent() { + return leader->recent; + } + CNode *Copy(int i) { + if (this != leader->recent) + return leader->recent->Copy(i); + CNode *copy = new CNode(nxt, data, i, false); + copy->leader = leader; + leader->recent = copy; + return copy; + } +}; + +class CopyQueue { +private: + std::vector front, back, nodes; + std::vector size; +public: + CopyQueue() { + front.push_back(NULL); + back.push_back(NULL); + size.push_back(0); + } + ~CopyQueue() { Clear(); } + void Clear() { + for(int i = 0; i < (int)nodes.size(); i++) { + delete nodes[i]; + } + back.clear(); back.push_back(NULL); + front.clear(); front.push_back(NULL); + size.clear(); size.push_back(0); + nodes.clear(); + } + int Front(int ver) { + return front[ver]->data; + } + void Pop() { + int i = LatestVersion(); + CNode *newFront = front[i]->GetRecent()->nxt; + if (newFront != NULL) newFront = newFront->GetRecent(); + front.push_back(newFront); + if (front.back() == NULL) back.push_back(NULL); + else back.push_back(back[i]->GetRecent()); + size.push_back(size[i]-1); + } + void Push(int data) { + int i = LatestVersion(); + CNode *newNode = new CNode(NULL, data, i+1); + nodes.push_back(newNode); + if (front[i] != NULL) { + CNode *copyBack = back[i]->Copy(i+1); + nodes.push_back(copyBack); + copyBack->nxt = newNode; + front.push_back(front[i]->GetRecent()); + } + else front.push_back(newNode); + back.push_back(newNode); + size.push_back(size[i]+1); + } + int Size(int ver) { + return size[ver]; + } + bool Empty(int ver) { + return size[ver] == 0; + } + int LatestVersion() { + return int(back.size())-1; + } +}; + +/* + * Persistent linked list queue with dynamic array + */ + +class AQueue { + std::vector front, back, nodes; + std::vector size; +public: + AQueue() { + front.push_back(NULL); + back.push_back(NULL); + size.push_back(0); + } + ~AQueue() { Clear(); } + void Clear() { + for(int i = 0; i < (int)nodes.size(); i++) { + delete nodes[i]; + } + nodes.clear(); + back.clear(); back.push_back(NULL); + front.clear(); front.push_back(NULL); + size.clear(); size.push_back(0); + } + int Front(int ver) { + return front[ver]->data; + } + void Pop() { + front.push_back(front.back()->nxt); + if (front.back() == NULL) back.push_back(NULL); + else back.push_back(back.back()); + size.push_back(size.back()-1); + } + void Push(int data) { + Node *newNode = new Node(NULL, data); + nodes.push_back(newNode); + if (front.back() != NULL) { + back.back()->nxt = newNode; + back.push_back(newNode); + front.push_back(front.back()); + } + else { + back.push_back(newNode); + front.push_back(newNode); + } + size.push_back(size.back()+1); + } + int Size(int ver) { + return size[ver]; + } + bool Empty(int ver) { + return size[ver] == 0; + } + int LatestVersion() { + return int(back.size())-1; + } +}; + +/* + * Persistent linked list queue with LA + */ + +struct PNode { + const int data; + std::vector par; + PNode(int _data) : + data(_data) { } +}; + +class PersistentQueue { +private: + std::vector back; + std::vector size; + std::vector nodes; + PNode *Newnode(PNode *parent, int data) { + PNode *node = new PNode(data); + if (parent != NULL) { + node->par.push_back(parent); + for(int i = 1; i-1 < (int)node->par[i-1]->par.size(); i++) { + node->par.push_back(node->par[i-1]->par[i-1]); + } + } + nodes.push_back(node); + return node; + } + PNode *LevelAncestor(PNode *node, int jump) { + for(int i = 0; i < (int)node->par.size(); i++) { + if (jump & (1<par[i]; + } + } + return node; + } +public: + PersistentQueue() { + back.push_back(NULL); + size.push_back(0); + } + ~PersistentQueue() { Clear(); } + void Clear() { + for(int i = 0; i < (int)nodes.size(); i++) { + delete nodes[i]; + } + back.clear(); back.push_back(NULL); + size.clear(); size.push_back(0); + nodes.clear(); + } + int Front(int ver) { + PNode *front = LevelAncestor(back[ver], size[ver]-1); + return front->data; + } + int Pop(int ver) { + back.push_back(back[ver]); + size.push_back(size[ver] - 1); + return int(back.size())-1; + } + int Push(int ver, int data) { + back.push_back(Newnode(back[ver], data)); + size.push_back(size[ver] + 1); + return int(back.size()) - 1; + } + int Size(int ver) { + return size[ver]; + } + int Empty(int ver) { + return size[ver] == 0; + } + int LatestVersion() { + return int(back.size())-1; + } +}; + +/* + * Unit tests + */ + +#include +#include +#include +#define NTESTS 10000 + +bool TestNormalQueue(bool push = false) { + srand(time(NULL)); + std::queue control; + Queue que; + for(int test = 1; test <= NTESTS; test++) { + int op = push ? 1 : rand()%2; + if (op == 0 && !control.empty()) { + control.pop(); + que.Pop(); + } + else { + int data = rand(); + que.Push(data); + control.push(data); + } + if (control.size() != que.Size()) { + printf("failed on test %d\n", test); + return false; + } + if (!control.empty()) { + int data1 = control.front(); + int data2 = que.Front(); + if (data1 != data2) { + printf("failed on test %d\n", test); + return false; + } + } + } + while(!control.empty()) { + int data1 = control.front(); + int data2 = que.Front(); + if (data1 != data2) { + printf("failed on closing loop %d-%d\n", data1, data2); + return false; + } + control.pop(); + que.Pop(); + } + printf("All normal queue tests passed, %s\n", + push ? "push only" : "push and pop" + ); + return true; +} + +bool TestPersistentQueueCorrectness(int suits, bool total, bool push = false) { + srand(time(NULL)); + for(int suit = 0; suit < suits; suit++) { + std::queue control[NTESTS]; + PersistentQueue que; + FatQueue fque; + CopyQueue cque; + AQueue aque; + for(int test = 1; test < NTESTS; test++) { + int op = push ? 1 : rand()%2; + int ver = total ? rand()%test : test-1; + control[test] = control[ver]; + if (op == 0 && !control[test].empty()) { + control[test].pop(); + que.Pop(ver); + if (!total) { + fque.Pop(); + cque.Pop(); + aque.Pop(); + } + } + else { + int data = rand(); + que.Push(ver, data); + control[test].push(data); + if (!total) { + fque.Push(data); + cque.Push(data); + aque.Push(data); + } + } + } + for(int test = 0; test < NTESTS; test++) { + if (control[test].size() != que.Size(test)) { + printf("LA queue size failed on test %d: %u-%d\n", test, control[test].size(), que.Size(test)); + return false; + } + if (!total && control[test].size() != fque.Size(test)) { + printf("Fat queue size failed on test %d: %u-%d\n", test, control[test].size(), fque.Size(test)); + return false; + } + if (!total && control[test].size() != cque.Size(test)) { + printf("Copy queue size failed on test %d: %u-%d\n", test, control[test].size(), cque.Size(test)); + return false; + } + if (!total && control[test].size() != aque.Size(test)) { + printf("Array queue size failed on test %d: %u-%d\n", test, control[test].size(), aque.Size(test)); + return false; + } + if (!control[test].empty()) { + int data1 = control[test].front(), data2; + data2 = que.Front(test); + if (data1 != data2) { + printf("LA front failed on test %d: %d-%d\n", test, data1, data2); + return false; + } + } + if (!total && !control[test].empty()) { + int data1 = control[test].front(), data2; + data2 = fque.Front(test); + if (data1 != data2) { + printf("Fat front failed on test %d: %d-%d\n", test, data1, data2); + return false; + } + data2 = cque.Front(test); + if (data1 != data2) { + printf("Copy front failed on test %d: %d-%d\n", test, data1, data2); + return false; + } + data2 = aque.Front(test); + if (data1 != data2) { + printf("Array front failed on test %d: %d-%d\n", test, data1, data2); + return false; + } + } + } + } + printf("All %s persistent queue tests passed, %s\n", + total ? "total" : "partial", + push ? "push only" : "push and pop" + ); + return true; +} + +bool TestPersistentQueueTime(int suits, bool total, bool push = false) { + long long seed = time(NULL); + srand(seed); + clock_t t; + t = clock(); //control + for(int suit = 0; suit < suits; suit++) { + std::queue control[NTESTS]; + for(int test = 1; test < NTESTS; test++) { + int op = push ? 1 : rand()%2; + int ver = total ? rand()%test : test-1; + control[test] = control[ver]; + if (op == 0 && !control[test].empty()) { + control[test].pop(); + } + else { + int data = rand(); + control[test].push(data); + } + } + for(int test = 0; test < NTESTS; test++) { + control[test].size(); + if(!control[test].empty()) + control[test].front(); + } + } + t = clock() - t; + printf("%s persistence control time, %s: %.0f us\n", + total ? "Total" : "Partial", + push ? "push only" : "push and pop", + t*1000000.0/CLOCKS_PER_SEC/suits + ); + t = clock(); //LA + for(int suit = 0; suit < suits; suit++) { + PersistentQueue que; + for(int test = 1; test < NTESTS; test++) { + int op = push ? 1 : rand()%2; + int ver = total ? rand()%test : test-1; + if (op == 0 && !que.Empty(ver)) { + que.Pop(ver); + } + else { + int data = rand(); + que.Push(ver, data); + } + } + for(int test = 0; test < NTESTS; test++) { + que.Size(test); + if (!que.Empty(test)) que.Front(test); + } + } + t = clock() - t; + printf("%s persistence LA time, %s: %.0f us\n", + total ? "Total" : "Partial", + push ? "push only" : "push and pop", + t*1000000.0/CLOCKS_PER_SEC/suits + ); + if (total) return true; + t = clock(); //fat + for(int suit = 0; suit < suits; suit++) { + FatQueue que; + for(int test = 1; test < NTESTS; test++) { + int op = push ? 1 : rand()%2; + int ver = test-1; + if (op == 0 && !que.Empty(ver)) { + que.Pop(); + } + else { + int data = rand(); + que.Push(data); + } + } + for(int test = 0; test < NTESTS; test++) { + que.Size(test); + if (!que.Empty(test)) que.Front(test); + } + } + t = clock() - t; + printf("%s persistence fat time, %s: %.0f us\n", + total ? "Total" : "Partial", + push ? "push only" : "push and pop", + t*1000000.0/CLOCKS_PER_SEC/suits + ); + t = clock(); //copy + for(int suit = 0; suit < suits; suit++) { + CopyQueue que; + for(int test = 1; test < NTESTS; test++) { + int op = push ? 1 : rand()%2; + int ver = test-1; + if (op == 0 && !que.Empty(ver)) { + que.Pop(); + } + else { + int data = rand(); + que.Push(data); + } + } + for(int test = 0; test < NTESTS; test++) { + que.Size(test); + if (!que.Empty(test)) que.Front(test); + } + } + t = clock() - t; + printf("%s persistence copy time, %s: %.0f us\n", + total ? "Total" : "Partial", + push ? "push only" : "push and pop", + t*1000000.0/CLOCKS_PER_SEC/suits + ); + t = clock(); //array + for(int suit = 0; suit < suits; suit++) { + AQueue que; + for(int test = 1; test < NTESTS; test++) { + int op = push ? 1 : rand()%2; + int ver = test-1; + if (op == 0 && !que.Empty(ver)) { + que.Pop(); + } + else { + int data = rand(); + que.Push(data); + } + } + for(int test = 0; test < NTESTS; test++) { + que.Size(test); + if (!que.Empty(test)) que.Front(test); + } + } + t = clock() - t; + printf("%s persistence array time, %s: %.0f us\n", + total ? "Total" : "Partial", + push ? "push only" : "push and pop", + t*1000000.0/CLOCKS_PER_SEC/suits + ); + return true; +} + +int main() { + TestNormalQueue(false); + TestPersistentQueueCorrectness(100, false, false); + TestPersistentQueueCorrectness(100, true, false); + TestPersistentQueueTime(100, false, false); + TestPersistentQueueTime(100, true, false); + TestNormalQueue(true); + TestPersistentQueueCorrectness(100, false, true); + TestPersistentQueueCorrectness(100, true, true); + TestPersistentQueueTime(100, false, true); + TestPersistentQueueTime(100, true, true); + return 0; +} \ No newline at end of file diff --git a/prdeque.cpp b/code/prdeque.cpp similarity index 100% rename from prdeque.cpp rename to code/prdeque.cpp diff --git a/psegtree.cpp b/code/psegtree.cpp similarity index 100% rename from psegtree.cpp rename to code/psegtree.cpp diff --git a/code/pstack.cpp b/code/pstack.cpp new file mode 100644 index 0000000..c107337 --- /dev/null +++ b/code/pstack.cpp @@ -0,0 +1,258 @@ +#include +#include + +/* + * Normal linked list stack + */ + +struct Node { + int data; + Node *nxt; + Node(Node *_nxt, int _data) : + nxt(_nxt), data(_data) { } +}; + +class Stack { +private: + Node* back; + int size; +public: + Stack() : + back(NULL), size(0) { } + ~Stack() { Clear(); } + void Clear() { + Node *aux; + while(back != NULL) { + aux = back; + back = back->nxt; + delete aux; + } + size = 0; + } + int Top() { + return back->data; + } + void Pop() { + Node *prv = back; + back = back->nxt; + delete prv; + size--; + } + void Push(int data) { + back = new Node(back, data); + size++; + } + int Size() { + return size; + } + bool Empty() { + return size == 0; + } +}; + +/* + * Persistent linked list stack + */ + +struct PNode { + int data, size; + PNode *nxt; + PNode(PNode *_nxt, int _data, int _size) : + nxt(_nxt), data(_data), size(_size) { } +}; + +class PersistentStack { +private: + std::vector back; + std::vector nodes; +public: + PersistentStack() { + back.push_back(NULL); + } + ~PersistentStack() { Clear(); } + void Clear() { + for(int i = 0; i < (int)nodes.size(); i++) { + delete nodes[i]; + } + back.clear(); back.push_back(NULL); + nodes.clear(); + } + int Top(int ver) { + return back[ver]->data; + } + int Pop(int ver) { + back.push_back(back[ver]->nxt); + return int(back.size())-1; + } + int Push(int ver, int data) { + back.push_back(new PNode(back[ver], data, Size(ver) + 1)); + nodes.push_back(back.back()); + return int(back.size())-1; + } + int Size(int ver) { + if (back[ver] == NULL) return 0; + return back[ver]->size; + } + int Empty(int ver) { + return Size(ver) == 0; + } + int LatestVersion() { + return int(back.size())-1; + } +}; + +/* + * Unit tests + */ + +#include +#include +#include +#define NTESTS 10000 + +bool TestNormalStack(bool push) { + srand(time(NULL)); + std::stack control; + Stack stck; + for(int test = 1; test <= NTESTS; test++) { + int op = push ? 1 : rand()%2; + if (op == 0 && !control.empty()) { + control.pop(); + stck.Pop(); + } + else { + int data = rand(); + stck.Push(data); + control.push(data); + } + if (control.size() != stck.Size()) { + printf("failed on test %d\n", test); + return false; + } + if (!control.empty()) { + int data1 = control.top(); + int data2 = stck.Top(); + if (data1 != data2) { + printf("failed on test %d\n", test); + return false; + } + } + } + printf("All normal stack tests passed, %s\n", + push ? "push only" : "push and pop" + ); + return true; +} + +bool TestPersistentStackCorrectness(int suits, bool total, bool push) { + long long seed = time(NULL); + srand(seed); + for(int suit = 0; suit < suits; suit++) { + std::stack control[NTESTS]; + PersistentStack stck; + for(int test = 1; test < NTESTS; test++) { + int op = push ? 1 : rand()%2; + int ver = total ? rand()%test : test-1; + control[test] = control[ver]; + + if (op == 0 && !control[test].empty()) { + control[test].pop(); + stck.Pop(ver); + } + else { + int data = rand(); + stck.Push(ver, data); + control[test].push(data); + } + } + for(int test = 0; test < NTESTS; test++) { + if (control[test].size() != stck.Size(test)) { + printf("failed on test %d\n", test); + return false; + } + if (!control[test].empty()) { + int data1 = control[test].top(); + int data2 = stck.Top(test); + if (data1 != data2) { + printf("failed on test %d\n", test); + return false; + } + } + } + } + printf("All %s persistent stack tests passed, %s\n", + total ? "total" : "partial", + push ? "push only" : "push and pop" + ); + return true; +} + +bool TestPersistentStackTime(int suits, bool total, bool push) { + long long seed = time(NULL); + srand(seed); + clock_t controlTime = clock(); + for(int suit = 0; suit < suits; suit++) { + std::stack control[NTESTS]; + for(int test = 1; test < NTESTS; test++) { + int op = push ? 1 : rand()%2; + int ver = total ? rand()%test : test-1; + control[test] = control[ver]; + + if (op == 0 && !control[test].empty()) { + control[test].pop(); + } + else { + int data = rand(); + control[test].push(data); + } + } + for(int test = 0; test < NTESTS; test++) { + control[test].size(); + if(!control[test].empty()) control[test].top(); + } + } + controlTime = clock() - controlTime; + srand(seed); + clock_t persistentTime = clock(); + for(int suit = 0; suit < suits; suit++) { + PersistentStack stck; + for(int test = 1; test < NTESTS; test++) { + int op = push ? 1 : rand()%2; + int ver = total ? rand()%test : test-1; + + if (op == 0 && !stck.Empty(ver)) { + stck.Pop(ver); + } + else { + int data = rand(); + stck.Push(ver, data); + } + } + for(int test = 0; test < NTESTS; test++) { + stck.Size(test); + if (!stck.Empty(test)) stck.Top(test); + } + } + persistentTime = clock() - persistentTime; + printf("Control time: %.0f us, %s Persistent time, %s: %.0f us\n", + controlTime*1000000.0/CLOCKS_PER_SEC/suits, + total ? "Total" : "Partial", + push ? "push only" : "push and pop", + persistentTime*1000000.0/CLOCKS_PER_SEC/suits + ); + return true; +} + +int main() { + TestNormalStack(false); + TestPersistentStackCorrectness(100, false, false); + TestPersistentStackCorrectness(100, true, false); + TestPersistentStackTime(100, false, false); + TestPersistentStackTime(100, true, false); + TestNormalStack(true); + TestPersistentStackCorrectness(100, false, true); + TestPersistentStackCorrectness(100, true, true); + TestPersistentStackTime(100, false, true); + TestPersistentStackTime(100, true, true); + return 0; +} \ No newline at end of file diff --git a/ptreap.cpp b/code/ptreap.cpp similarity index 100% rename from ptreap.cpp rename to code/ptreap.cpp diff --git a/code/punionfind.cpp b/code/punionfind.cpp new file mode 100644 index 0000000..2ba812a --- /dev/null +++ b/code/punionfind.cpp @@ -0,0 +1,41 @@ +#include +#include + +struct Node { + Node *parent; + int rank; + Node(Node *_parent, int _rank) : + parent(parent), rank(_rank) { } + Node() : + parent(this), rank(0) { } +} + +class UnionFind { +private: + std::vector nodes; + Node *Find(Node *node) { + if (node == node->parent) return node; + else return Find(node->parent); + } +public: + UnionFind(int N = 0) { Clear(N); } + ~UnionFind() { Clear(0); } + void Clear(int N) { + nodes.resize(N); + for (int i = 0; i < N; i++) nodes[i] = new Node(); + } + bool IsSameSet(Node *u, Node *v) { + return Find(u) == Find(v); + } + void unionSet (int i, int j) { + Node *u = &nodes[i]; + Node *v = &nodes[j]; + if (IsSameSet(u, v)) return; + int x = find(i), y = find(j); + if (rank[x] > rank[y]) parent[y] = x; + else { + parent[x] = y; + if (rank[x] == rank[y]) rank[y]++; + } + } +}; \ No newline at end of file diff --git a/estudo-sobre-estruturas.pdf b/estudo-sobre-estruturas.pdf new file mode 100644 index 0000000..dccdf87 Binary files /dev/null and b/estudo-sobre-estruturas.pdf differ diff --git a/pdeque.cpp b/pdeque.cpp deleted file mode 100644 index 30d5a92..0000000 --- a/pdeque.cpp +++ /dev/null @@ -1,340 +0,0 @@ -#include -#include - -/* - * Normal linked list deque - */ - -struct Node { - const int data; - Node *nxt, *prv; - Node(Node *_nxt, Node *_prv, int _data) : - nxt(_nxt), prv(_prv), data(_data) { } -}; - -class Deque { -private: - Node *front, *back; - int size; -public: - Deque() : - front(NULL), back(NULL), size(0) {} - ~Deque() { Clear(); } - void Clear() { - Node *aux; - while(front != NULL) { - aux = front; - front = front->nxt; - delete aux; - } - back = NULL; - size = 0; - } - int Front() { - return front->data; - } - int Back() { - return back->data; - } - void PopFront() { - Node *aux = front; - front = front->nxt; - delete aux; - if (front == NULL) back = NULL; - else front->prv = NULL; - size--; - } - void PopBack() { - Node *aux = back; - back = back->prv; - delete aux; - if (back == NULL) front = NULL; - else back->nxt = NULL; - size--; - } - void PushBack(int data) { - if (back != NULL) back = back->nxt = new Node(NULL, back, data); - else front = back = new Node(NULL, NULL, data); - size++; - } - void PushFront(int data) { - if (front != NULL) front = front->prv = new Node(front, NULL, data); - else front = back = new Node(NULL, NULL, data); - size++; - } - int Size() { - return size; - } - bool Empty() { - return size == 0; - } -}; - -/* - * Persistent linked list deque with LA and LCA - */ - -struct PNode { - const int data, depth; - std::vector par; - PNode(int _data, int _depth) : - data(_data), depth(_depth) { } -}; - -class PersistentDeque { -private: - std::vector front, back; - std::vector nodes; - PNode *Newnode(PNode *parent, int data) { - PNode *node; - if (parent != NULL) { - node = new PNode(data, parent->depth + 1); - node->par.push_back(parent); - for(int i = 1; i-1 < (int)node->par[i-1]->par.size(); i++) { - node->par.push_back(node->par[i-1]->par[i-1]); - } - } - else node = new PNode(data, 1); - nodes.push_back(node); - return node; - } - PNode *LowestCommonAncestor(PNode *u, PNode *v) { - if (u == NULL || v == NULL) return NULL; - u = LevelAncestor(u, u->depth - v->depth); - v = LevelAncestor(v, v->depth - u->depth); - if (u == v) return u; - for(int i = int(u->par.size()) - 1; i>= 0; i--) { - while(i < (int)u->par.size() && u->par[i] != v->par[i]) { - u = u->par[i]; - v = v->par[i]; - } - } - return u->par[0]; - } - PNode *LevelAncestor(PNode *node, int jump) { - if (node == NULL || jump <= 0) return node; - for(int i = 0; i < (int)node->par.size(); i++) { - if (jump & (1<par[i]; - } - } - return node; - } -public: - PersistentDeque() { Clear(); } - ~PersistentDeque() { Clear(); } - void Clear() { - for(int i = 0; i < (int)nodes.size(); i++) { - delete nodes[i]; - } - nodes.clear(); - back.clear(); back.push_back(NULL); - front.clear(); front.push_back(NULL); - } - int Front(int ver) { - return front[ver]->data; - } - int Back(int ver) { - return back[ver]->data; - } - int PopFront(int ver) { - if (front[ver] == back[ver]) { - back.push_back(NULL); - front.push_back(NULL); - return int(front.size())-1; - } - PNode *lca = LowestCommonAncestor(front[ver], back[ver]); - back.push_back(back[ver]); - if (front[ver] == lca) { - PNode *la = LevelAncestor(back[ver], back[ver]->depth - lca->depth - 1); - front.push_back(la); - } - else front.push_back(front[ver]->par[0]); - return int(front.size())-1; - } - int PopBack(int ver) { - if (front[ver] == back[ver]) { - back.push_back(NULL); - front.push_back(NULL); - return int(back.size())-1; - } - PNode *lca = LowestCommonAncestor(front[ver], back[ver]); - front.push_back(front[ver]); - if (back[ver] == lca) { - PNode *la = LevelAncestor(front[ver], front[ver]->depth - lca->depth - 1); - back.push_back(la); - } - else back.push_back(back[ver]->par[0]); - return int(back.size())-1; - } - int PushFront(int ver, int data) { - PNode *node = Newnode(front[ver], data); - front.push_back(node); - if (back[ver] == NULL) back.push_back(node); - else back.push_back(back[ver]); - return int(front.size()) - 1; - } - int PushBack(int ver, int data) { - PNode *node = Newnode(back[ver], data); - back.push_back(node); - if (front[ver] == NULL) front.push_back(node); - else front.push_back(front[ver]); - return int(back.size()) - 1; - } - int At(int ver, int i) { - PNode *lca = LowestCommonAncestor(front[ver], back[ver]); - int frontDist = front[ver]->depth - lca->depth; - int backDist = back[ver]->depth - lca->depth; - PNode *node; - if (i <= frontDist) node = LevelAncestor(front[ver], i); - else node = LevelAncestor(back[ver], frontDist + backDist - i); - return node->data; - } - int Size(int ver) { - PNode *lca = LowestCommonAncestor(front[ver], back[ver]); - if (lca == NULL) return 0; - return front[ver]->depth + back[ver]->depth - 2*lca->depth + 1; - } - int LatestVersion() { - return int(back.size())-1; - } -}; - -/* - * Unit tests - */ - -#include -#include -#include -#include -#define NTESTS 10000 -#define RANGE 1000 - -bool TestNormalDeque() { - srand(time(NULL)); - std::list control; - Deque deq; - for(int test = 1; test <= NTESTS || !control.empty(); test++) { - int add = rand()%2; - int front = rand()%2; - if (add && test <= NTESTS) { - int data = rand()%RANGE; - if (front) { - control.push_front(data); - deq.PushFront(data); - } - else { - control.push_back(data); - deq.PushBack(data); - } - } - else { - if (control.empty()) { - test--; - continue; - } - if (front) { - control.pop_front(); - deq.PopFront(); - } - else { - control.pop_back(); - deq.PopBack(); - } - } - if (control.size() != deq.Size()) { - printf("failed on size test %d\n", test); - return false; - } - if (!control.empty()) { - int data1 = control.front(); - int data2 = deq.Front(); - if (data1 != data2) { - printf("failed on front test %d: %d-%d\n", test, data1, data2); - return false; - } - data1 = control.back(); - data2 = deq.Back(); - if (data1 != data2) { - printf("failed on back test %d: %d-%d\n", test, data1, data2); - return false; - } - } - } - printf("All normal deque tests passed\n"); - return true; -} - -bool TestPersistentDeque() { - srand(time(NULL)); - std::deque control[NTESTS]; - PersistentDeque deq; - for(int test = 1; test < NTESTS; test++) { - int add = rand()%2; - int front = rand()%2; - int ver = rand()%test; - control[test] = control[ver]; - if (add) { - int data = rand()%RANGE; - if (front) { - control[test].push_front(data); - deq.PushFront(ver, data); - } - else { - control[test].push_back(data); - deq.PushBack(ver, data); - } - } - else { - if (control[test].empty()) { - test--; - continue; - } - if (front) { - control[test].pop_front(); - deq.PopFront(ver); - } - else { - control[test].pop_back(); - deq.PopBack(ver); - } - } - } - for(int test = 0; test < NTESTS; test++) { - if (control[test].size() != deq.Size(test)) { - printf("failed on size test %d\n", test); - return false; - } - if (!control[test].empty()) { - int data1 = control[test].front(); - int data2 = deq.Front(test); - if (data1 != data2) { - printf("failed on front test %d: %d-%d\n", test, data1, data2); - return false; - } - data1 = control[test].back(); - data2 = deq.Back(test); - if (data1 != data2) { - printf("failed on back test %d: %d-%d\n", test, data1, data2); - return false; - } - } - for(int i = 0; i < (int)control[test].size(); i++) { - int data1 = control[test][i]; - int data2 = deq.At(test, i); - if (data1 != data2) { - printf("failed on at %d test %d: %d-%d\n", i, test, data1, data2); - return false; - } - } - } - printf("All persistent deque tests passed\n"); - return true; -} - -int main() { - TestNormalDeque(); - TestPersistentDeque(); - return 0; -} \ No newline at end of file diff --git a/pqueue.cpp b/pqueue.cpp deleted file mode 100644 index c422c9b..0000000 --- a/pqueue.cpp +++ /dev/null @@ -1,220 +0,0 @@ -#include -#include - -/* - * Normal linked list queue - */ - -struct Node { - const int data; - Node *nxt; - Node(Node *_nxt, int _data) : - nxt(_nxt), data(_data) { } -}; - -class Queue { -private: - Node *front, *back; - int size; -public: - Queue() : - front(NULL), back(NULL), size(0) {} - ~Queue() { Clear(); } - void Clear() { - while(front != NULL) { - Node *aux = front; - front = front->nxt; - delete aux; - } - back = NULL; - size = 0; - } - int Front() { - return front->data; - } - void Pop() { - Node *prv = front; - front = front->nxt; - delete prv; - size--; - if (front == NULL) back = NULL; - } - void Push(int data) { - if (front != NULL) back = back->nxt = new Node(NULL, data); - else front = back = new Node(NULL, data); - size++; - } - int Size() { - return size; - } - bool Empty() { - return size == 0; - } -}; - -/* - * Persistent linked list queue with LA - */ - -struct PNode { - const int data; - std::vector par; - PNode(int _data) : - data(_data) { } -}; - -class PersistentQueue { -private: - std::vector back; - std::vector size; - std::vector nodes; - PNode *Newnode(PNode *parent, int data) { - PNode *node = new PNode(data); - if (parent != NULL) { - node->par.push_back(parent); - for(int i = 1; i-1 < (int)node->par[i-1]->par.size(); i++) { - node->par.push_back(node->par[i-1]->par[i-1]); - } - } - nodes.push_back(node); - return node; - } - PNode *LevelAncestor(PNode *node, int jump) { - for(int i = 0; i < (int)node->par.size(); i++) { - if (jump & (1<par[i]; - } - } - return node; - } -public: - PersistentQueue() { - back.push_back(NULL); - size.push_back(0); - } - ~PersistentQueue() { Clear(); } - void Clear() { - for(int i = 0; i < (int)nodes.size(); i++) { - delete nodes[i]; - } - back.clear(); back.push_back(NULL); - size.clear(); size.push_back(0); - nodes.clear(); - } - int Front(int ver) { - PNode *front = LevelAncestor(back[ver], size[ver]-1); - return front->data; - } - int Pop(int ver) { - back.push_back(back[ver]); - size.push_back(size[ver] - 1); - return int(back.size())-1; - } - int Push(int ver, int data) { - back.push_back(Newnode(back[ver], data)); - size.push_back(size[ver] + 1); - return int(back.size()) - 1; - } - int Size(int ver) { - return size[ver]; - } - int Empty(int ver) { - return size[ver] == 0; - } - int LatestVersion() { - return int(back.size())-1; - } -}; - -/* - * Unit tests - */ - -#include -#include -#include -#define NTESTS 10000 - -bool TestNormalQueue() { - srand(time(NULL)); - std::queue control; - Queue que; - for(int test = 1; test <= NTESTS; test++) { - int op = rand()%2; - if (op == 0 && !control.empty()) { - control.pop(); - que.Pop(); - } - else { - int data = rand(); - que.Push(data); - control.push(data); - } - if (control.size() != que.Size()) { - printf("failed on test %d\n", test); - return false; - } - if (!control.empty()) { - int data1 = control.front(); - int data2 = que.Front(); - if (data1 != data2) { - printf("failed on test %d\n", test); - return false; - } - } - } - while(!control.empty()) { - int data1 = control.front(); - int data2 = que.Front(); - if (data1 != data2) { - printf("failed on closing loop %d-%d\n", data1, data2); - return false; - } - control.pop(); - que.Pop(); - } - printf("All normal queue tests passed\n"); - return true; -} - -bool TestPersistentQueue() { - srand(time(NULL)); - std::queue control[NTESTS]; - PersistentQueue que; - for(int test = 1; test < NTESTS; test++) { - int op = rand()%2; - int ver = rand()%test; - control[test] = control[ver]; - if (op == 0 && !control[test].empty()) { - control[test].pop(); - que.Pop(ver); - } - else { - int data = rand(); - que.Push(ver, data); - control[test].push(data); - } - } - for(int test = 0; test < NTESTS; test++) { - if (control[test].size() != que.Size(test)) { - printf("size failed on test %d: %u-%d\n", test, control[test].size(), que.Size(test)); - return false; - } - if (!control[test].empty()) { - int data1 = control[test].front(); - int data2 = que.Front(test); - if (data1 != data2) { - printf("front failed on test %d: %d-%d\n", test, data1, data2); - return false; - } - } - } - printf("All persistent queue tests passed\n"); - return true; -} - -int main() { - TestNormalQueue(); - TestPersistentQueue(); - return 0; -} \ No newline at end of file diff --git a/pstack.cpp b/pstack.cpp deleted file mode 100644 index 4f78584..0000000 --- a/pstack.cpp +++ /dev/null @@ -1,185 +0,0 @@ -#include -#include - -/* - * Normal linked list stack - */ - -struct Node { - int data; - Node *nxt; - Node(Node *_nxt, int _data) : - nxt(_nxt), data(_data) { } -}; - -class Stack { -private: - Node* back; - int size; -public: - Stack() : - back(NULL), size(0) { } - ~Stack() { Clear(); } - void Clear() { - Node *aux; - while(back != NULL) { - aux = back; - back = back->nxt; - delete aux; - } - size = 0; - } - int Top() { - return back->data; - } - void Pop() { - Node *prv = back; - back = back->nxt; - delete prv; - size--; - } - void Push(int data) { - back = new Node(back, data); - size++; - } - int Size() { - return size; - } - bool Empty() { - return size == 0; - } -}; - -/* - * Persistent linked list stack - */ - -struct PNode { - int data, size; - PNode *nxt; - PNode(PNode *_nxt, int _data, int _size) : - nxt(_nxt), data(_data), size(_size) { } -}; - -class PersistentStack { -private: - std::vector back; - std::vector nodes; -public: - PersistentStack() { - back.push_back(NULL); - } - ~PersistentStack() { Clear(); } - void Clear() { - for(int i = 0; i < (int)nodes.size(); i++) { - delete nodes[i]; - } - back.clear(); back.push_back(NULL); - nodes.clear(); - } - int Top(int ver) { - return back[ver]->data; - } - int Pop(int ver) { - back.push_back(back[ver]->nxt); - return int(back.size())-1; - } - int Push(int ver, int data) { - back.push_back(new PNode(back[ver], data, Size(ver) + 1)); - nodes.push_back(back.back()); - return int(back.size())-1; - } - int Size(int ver) { - if (back[ver] == NULL) return 0; - return back[ver]->size; - } - int Empty(int ver) { - return Size(ver) == 0; - } - int LatestVersion() { - return int(back.size())-1; - } -}; - -/* - * Unit tests - */ - -#include -#include -#include -#define NTESTS 10000 - -bool TestNormalStack() { - srand(time(NULL)); - std::stack control; - Stack stck; - for(int test = 1; test <= NTESTS; test++) { - int op = rand()%2; - if (op == 0 && !control.empty()) { - control.pop(); - stck.Pop(); - } - else { - int data = rand(); - stck.Push(data); - control.push(data); - } - if (control.size() != stck.Size()) { - printf("failed on test %d\n", test); - return false; - } - if (!control.empty()) { - int data1 = control.top(); - int data2 = stck.Top(); - if (data1 != data2) { - printf("failed on test %d\n", test); - return false; - } - } - } - printf("All normal stack tests passed\n"); - return true; -} - -bool TestPersistentStack() { - srand(time(NULL)); - std::stack control[NTESTS]; - PersistentStack stck; - for(int test = 1; test < NTESTS; test++) { - int op = rand()%2; - int ver = rand()%test; - control[test] = control[ver]; - if (op == 0 && !control[test].empty()) { - control[test].pop(); - stck.Pop(ver); - } - else { - int data = rand(); - stck.Push(ver, data); - control[test].push(data); - } - } - for(int test = 0; test < NTESTS; test++) { - if (control[test].size() != stck.Size(test)) { - printf("failed on test %d\n", test); - return false; - } - if (!control[test].empty()) { - int data1 = control[test].top(); - int data2 = stck.Top(test); - if (data1 != data2) { - printf("failed on test %d\n", test); - return false; - } - } - } - printf("All persistent stack tests passed\n"); - return true; -} - -int main() { - TestNormalStack(); - TestPersistentStack(); - return 0; -} \ No newline at end of file