Files
912-notes/thu_dsa/chp9/skiplist.h
2019-11-08 16:14:27 +08:00

174 lines
4.1 KiB
C++

#ifndef SKIPLIST_H_
#define SKIPLIST_H_
#include "dict.h"
#include "quadlist.h"
#include "../chp3/List.h"
#include <iostream>
#include <iomanip>
#include <cstdlib>
#include <cassert>
#include <ctime>
using std::cerr;
using std::endl;
template <typename K, typename V>
class entry{
public:
K key;
V value;
entry() = default;
entry(K key, V value) : key(key), value(value) {}
bool operator==(entry const &e){
return key == e.key;
}
};
template <typename K, typename V>
class SkipList: Dict<K, V>, List<QuadList<entry<K, V>>*>{
protected:
QuadNode<entry<K, V>>* skipSearch(K key);
public:
//constructor
SkipList();
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);
}
//internal methods
template <typename K, typename V>
QuadNode<entry<K, V>>* SkipList<K, V>::skipSearch(K key) {
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;
qnode = qnode->prev;
if (qnode->entry.key == key) return qnode;
//else
if (qnode->below == nullptr) return qnode;
//else
qnode = qnode->below;
}
}
//external interfaces
template <typename K, typename V>
V SkipList<K, V>::get(K key){
QuadNode<entry<K, V>>* res;
res = skipSearch(key);
//assert(res->next->entry.key > key);
if(res->entry.key != key){
cerr << "key:" << key << "is not in SkipList!" << endl;
}
return res->entry.value;
}
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();
QuadList<entry<K, V>> *newlist;
while (qnode->below != nullptr) qnode = qnode->below;
qlist->val->insert_after_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);
}
while(rand() % 2 == 0){
belowNode = qnode->next;
qlist = next(qlist);
while (qnode->above == nullptr) qnode = qnode->prev;
qnode = qnode->above;
qlist->val->insert_after_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;
}
template <typename K, typename V>
bool SkipList<K, V>::remove(K key){
QuadNode<entry<K, V>>* qnode = skipSearch(key);
QuadNode<entry<K, V>>* tempNode;
ListNode<QuadList<entry<K, V>>*>* qlist = first();
if (qnode->entry.key != key) return false;
//else
while (qnode->below) qnode = qnode->below;
while(qnode){
tempNode = qnode;
qlist->val->remove(qnode);
qnode = qnode->above;
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