diff --git a/thu_dsa/chp3/List.h b/thu_dsa/chp3/List.h index c91452c..1dfa868 100644 --- a/thu_dsa/chp3/List.h +++ b/thu_dsa/chp3/List.h @@ -27,8 +27,8 @@ public: //read-only interfaces ListNodePosi(T) first() const { return head->succ; } ListNodePosi(T) last() const { return tail->prev; } - ListNodePosi(T) prev(ListNodePosi(T) p) const { return p->prev; } - ListNodePosi(T) next(ListNodePosi(T) p) const { return p->next; } + ListNodePosi(T) prev(ListNodePosi(T) p) const { return p->prev == head? nullptr: p->prev; } + ListNodePosi(T) next(ListNodePosi(T) p) const { return p->succ == tail? nullptr: p->succ; } ListNodePosi(T) find(T const &val) const { return find(val, size, tail); } //find val from all elements of the list ListNodePosi(T) find(T const &val, int n, ListNodePosi(T) p) const; //find val from a range of n elements before p ListNodePosi(T) search(T const &val, int n, ListNodePosi(T) p) const; //find val in a sorted List diff --git a/thu_dsa/chp9/dict.h b/thu_dsa/chp9/dict.h index b5d121d..7b15312 100644 --- a/thu_dsa/chp9/dict.h +++ b/thu_dsa/chp9/dict.h @@ -5,7 +5,7 @@ template class Dict{ public: - virtual int size() = 0; + virtual int size() const = 0; virtual V get(K key) = 0; virtual bool put(K key, V value) = 0; virtual bool remove(K key) = 0; diff --git a/thu_dsa/chp9/quadlist.h b/thu_dsa/chp9/quadlist.h index e973eda..ccd4dfb 100644 --- a/thu_dsa/chp9/quadlist.h +++ b/thu_dsa/chp9/quadlist.h @@ -29,20 +29,20 @@ public: //constructor QuadList(); - //deconstrutor - ~QuadList(); - //external interfaces //read-only interfaces int size() const { return __size; } bool empty() const { return size() == 0; } - QuadNodePosi(T) first() const { return empty()? nullptr : __head->next;} - QuadNodePosi(T) last() const { return empty()? nullptr : __tail->prev;} + QuadNodePosi(T) first() const { return __head->next;} + QuadNodePosi(T) last() const { return __tail->prev;} QuadNodePosi(T) prev(QuadNodePosi(T) p) const { return p->prev; } QuadNodePosi(T) next(QuadNodePosi(T) p) const { return p->next; } //writable interfaces + void sethead(T entry) { __head->entry = entry; } + void settail(T entry) { __tail->entry = entry; } + void connectTo(QuadList* down); void insert_before_above(QuadNodePosi(T) p, T const& entry, QuadNodePosi(T) base = nullptr); void insert_after_above(QuadNodePosi(T)p, T const & entry, QuadNodePosi(T) base = nullptr); void remove(QuadNodePosi(T) p); @@ -51,15 +51,26 @@ public: //constructor template QuadList::QuadList(){ - __head = new QuadNode(MININT); - __tail = new QuadNode(MAXINT); + __head = new QuadNode(); + __tail = new QuadNode(); __size = 0; __head->next = __tail; + __head->prev = __tail; + __tail->next = __head; __tail->prev = __head; } //writable interfaces +template +void QuadList::connectTo(QuadList* down){ + //assert(down != nullptr); + __head->below = down->__head; + __tail->below = down->__tail; + down->__head->above = __head; + down->__tail->above = __tail; +} + template void QuadList::insert_before_above(QuadNodePosi(T) p, T const & entry, QuadNodePosi(T) base){ QuadNodePosi(T) newNode = new QuadNode(entry); @@ -67,7 +78,7 @@ void QuadList::insert_before_above(QuadNodePosi(T) p, T const & entry, QuadNo newNode->prev = p->prev; p->prev = newNode; newNode->prev->next = newNode; - base->above = newNode; + if(base) base->above = newNode; newNode->below = base; ++__size; } diff --git a/thu_dsa/chp9/skiplist.h b/thu_dsa/chp9/skiplist.h index 547dac9..4c6379a 100644 --- a/thu_dsa/chp9/skiplist.h +++ b/thu_dsa/chp9/skiplist.h @@ -5,6 +5,7 @@ #include "quadlist.h" #include "../chp3/List.h" #include +#include #include #include @@ -20,7 +21,7 @@ public: entry() = default; entry(K key, V value) : key(key), value(value) {} - operator==(entry const &e){ + bool operator==(entry const &e){ return key == e.key; } }; @@ -34,18 +35,21 @@ public: //constructor SkipList(); - int size() const { return first()->size(); } + int size() const { return first()->val->size(); } int level() const { return getSize(); } V get(K key); bool put(K key, V value); bool remove(K key); + void print() const; }; //constructor template SkipList::SkipList(){ QuadList>* qlist = new QuadList>(); + qlist->sethead(entry(MININT, 0)); + qlist->settail(entry(MAXINT, 0)); push_back(qlist); } @@ -53,8 +57,8 @@ SkipList::SkipList(){ template QuadNode>* SkipList::skipSearch(K key) { - while (1) { - QuadNode>* qnode = last()->first(); //the first quadlist node of the last quadlist + QuadNode>* qnode = last()->val->first(); //the first quadlist node of the last quadlist + while (1) { while (qnode->entry.key < key) qnode = qnode->next; if (qnode->entry.key == key) return qnode; //else @@ -81,22 +85,33 @@ template bool SkipList::put(K key, V value){ QuadNode>* qnode = skipSearch(key); QuadNode>* belowNode; - ListNode>*>* qlist = first(); + ListNode>*> *qlist = first(); + QuadList> *newlist; while (qnode->below != nullptr) qnode = qnode->below; if (qnode->entry.key != key) qnode = qnode->next; qlist->val->insert_before_above(qnode, entry(key, value)); + if (next(qlist) == nullptr) { + newlist = new QuadList>(); + newlist->sethead(entry(MININT, 0)); + newlist->settail(entry(MAXINT, 0)); + newlist->connectTo(qlist->val); + push_back(newlist); + } - srand((int)time(0)); - while(rand() & 1){ + while(rand() % 2 == 0){ belowNode = qnode->prev; qlist = next(qlist); - if(qlist->val->empty()){ - push_back(new QuadList>()); - } while (qnode->above == nullptr) qnode = qnode->next; qnode = qnode->above; qlist->val->insert_before_above(qnode, entry(key, value), belowNode); + if (next(qlist) == nullptr) { + newlist = new QuadList>(); + newlist->sethead(entry(MININT, 0)); + newlist->settail(entry(MAXINT, 0)); + newlist->connectTo(qlist->val); + push_back(newlist); + } } return true; } @@ -114,10 +129,44 @@ bool SkipList::remove(K key){ tempNode = qnode; qlist->val->remove(qnode); qnode = qnode->above; - qlist = qlist->val->next(); + qlist = next(qlist); delete tempNode; } + + //remove level if empty + qlist = prev(last()); + while(qlist && qlist->val->empty()){ + pop_back(); + qlist = prev(qlist); + } + return true; } +template +void SkipList::print() const{ + QuadList>* qlist = first()->val; + QuadNode>* qnode; + QuadNode>* tempNode; + int* currLevel = new int[size()], idx = 0; + for(qnode = qlist->first(); qnode->entry.key != MAXINT; qnode = qnode->next){ + currLevel[idx] = 0; + tempNode = qnode; + while(tempNode){ + currLevel[idx]++; + tempNode = tempNode->above; + } + ++idx; + } + + for (int jx = level(); jx != 0; --jx) { + idx = 0; + for (qnode = qlist->first(); qnode->entry.key != MAXINT; qnode = qnode->next){ + if (currLevel[idx++] >= jx) cout << qnode->entry.key << '\t'; + else cout << " " << '\t'; + } + cout << endl; + } +} + #endif diff --git a/thu_dsa/chp9/test_skiplist.cpp b/thu_dsa/chp9/test_skiplist.cpp new file mode 100644 index 0000000..0c09aab --- /dev/null +++ b/thu_dsa/chp9/test_skiplist.cpp @@ -0,0 +1,52 @@ +#include "skiplist.h" +#include +#include + +using std::cout; +using std::endl; + +void basic_test(); +void insert_delete_test(); + +int main(){ + cout << "begin tests ..." << endl; + + basic_test(); + insert_delete_test(); + + cout << "All tests passed." << endl; + system("pause"); + return 0; +} + +void basic_test(){ + SkipList slist; + assert(slist.size() == 0); + assert(slist.level() == 1); + slist.print(); + + assert(slist.remove(0) == false); + + cout << "basic_test passed." << endl; +} + +void insert_delete_test(){ + SkipList slist; + int src[15] = { 5, 9, 0, 2, 3, 6, 1, 7, 4, 8, 3, 8, 4, 7, 7 }; + srand((unsigned int)time(0)); + for (int ix = 0; ix != 15; ++ix) { + slist.put(src[ix], src[ix]); + cout << "This is the " << ix + 1 << "th insert, the level is " << slist.level() << endl; + slist.print(); + } + + cout << endl; + + for(int ix = 0; ix != 15; ++ix){ + slist.remove(src[ix]); + cout << "This is the " << ix + 1 << "th delete, the level is " << slist.level() << endl; + slist.print(); + } + + cout << "insert_delete test passed." << endl; +}