debug skiplist, all tests passed. But I sincerely doubt my coding ability.
This commit is contained in:
@@ -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<T>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
template <typename K, typename V>
|
||||
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;
|
||||
|
||||
@@ -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<T>* 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 <typename T>
|
||||
QuadList<T>::QuadList(){
|
||||
__head = new QuadNode<T>(MININT);
|
||||
__tail = new QuadNode<T>(MAXINT);
|
||||
__head = new QuadNode<T>();
|
||||
__tail = new QuadNode<T>();
|
||||
__size = 0;
|
||||
__head->next = __tail;
|
||||
__head->prev = __tail;
|
||||
__tail->next = __head;
|
||||
__tail->prev = __head;
|
||||
}
|
||||
|
||||
//writable interfaces
|
||||
|
||||
template <typename T>
|
||||
void QuadList<T>::connectTo(QuadList<T>* down){
|
||||
//assert(down != nullptr);
|
||||
__head->below = down->__head;
|
||||
__tail->below = down->__tail;
|
||||
down->__head->above = __head;
|
||||
down->__tail->above = __tail;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void QuadList<T>::insert_before_above(QuadNodePosi(T) p, T const & entry, QuadNodePosi(T) base){
|
||||
QuadNodePosi(T) newNode = new QuadNode<T>(entry);
|
||||
@@ -67,7 +78,7 @@ void QuadList<T>::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;
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "quadlist.h"
|
||||
#include "../chp3/List.h"
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <cstdlib>
|
||||
#include <ctime>
|
||||
|
||||
@@ -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 <typename K, typename V>
|
||||
SkipList<K, V>::SkipList(){
|
||||
QuadList<entry<K, V>>* qlist = new QuadList<entry<K, V>>();
|
||||
qlist->sethead(entry<K, V>(MININT, 0));
|
||||
qlist->settail(entry<K, V>(MAXINT, 0));
|
||||
push_back(qlist);
|
||||
}
|
||||
|
||||
@@ -53,8 +57,8 @@ SkipList<K, V>::SkipList(){
|
||||
|
||||
template <typename K, typename V>
|
||||
QuadNode<entry<K, V>>* SkipList<K, V>::skipSearch(K key) {
|
||||
while (1) {
|
||||
QuadNode<entry<K, V>>* qnode = last()->first(); //the first quadlist node of the last quadlist
|
||||
QuadNode<entry<K, V>>* 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 <typename K, typename V>
|
||||
bool SkipList<K, V>::put(K key, V value){
|
||||
QuadNode<entry<K, V>>* qnode = skipSearch(key);
|
||||
QuadNode<entry<K, V>>* belowNode;
|
||||
ListNode<QuadList<entry<K, V>>*>* qlist = first();
|
||||
ListNode<QuadList<entry<K, V>>*> *qlist = first();
|
||||
QuadList<entry<K, V>> *newlist;
|
||||
|
||||
while (qnode->below != nullptr) qnode = qnode->below;
|
||||
if (qnode->entry.key != key) qnode = qnode->next;
|
||||
qlist->val->insert_before_above(qnode, entry<K, V>(key, value));
|
||||
if (next(qlist) == nullptr) {
|
||||
newlist = new QuadList<entry<K, V>>();
|
||||
newlist->sethead(entry<K, V>(MININT, 0));
|
||||
newlist->settail(entry<K, V>(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<entry<K, V>>());
|
||||
}
|
||||
while (qnode->above == nullptr) qnode = qnode->next;
|
||||
qnode = qnode->above;
|
||||
qlist->val->insert_before_above(qnode, entry<K, V>(key, value), belowNode);
|
||||
if (next(qlist) == nullptr) {
|
||||
newlist = new QuadList<entry<K, V>>();
|
||||
newlist->sethead(entry<K, V>(MININT, 0));
|
||||
newlist->settail(entry<K, V>(MAXINT, 0));
|
||||
newlist->connectTo(qlist->val);
|
||||
push_back(newlist);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -114,10 +129,44 @@ bool SkipList<K, V>::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 <typename K, typename V>
|
||||
void SkipList<K, V>::print() const{
|
||||
QuadList<entry<K, V>>* qlist = first()->val;
|
||||
QuadNode<entry<K, V>>* qnode;
|
||||
QuadNode<entry<K, V>>* 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
|
||||
|
||||
52
thu_dsa/chp9/test_skiplist.cpp
Normal file
52
thu_dsa/chp9/test_skiplist.cpp
Normal file
@@ -0,0 +1,52 @@
|
||||
#include "skiplist.h"
|
||||
#include <iostream>
|
||||
#include <cassert>
|
||||
|
||||
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<int, int> 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<int, int> 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;
|
||||
}
|
||||
Reference in New Issue
Block a user