1.废话
我怀念的C++,好久不见。是晚上12点开始看跳表的,只是觉得这么牛逼的数据结构为什么本科没有学到呢?终于搞定。
2.introduction
许多人应该对数据结构中的链表有所印象。记得那时候老师说的最多的线性表寻址方便,增删操作麻烦,而链表正好相反。那么有没有一种数据结构能得两者之精华呢?跳表就是牺牲空间换时间的最好case,寻址操作是log(n),增减又方便。和普通的链表分别在于,他储存的并不仅仅是后面一个节点的地址,而是根据一个得到的随机数的大小来决定储存的数量。个人观点是链表的头节点的高度就是跳表的深度(深度会改变)。关于概念部分,不再引述,读者可以随意google。
3.code
在这里用到模板和面向对象概念。(没有很严格的用到oop,主要考虑code的简洁性,set,get操作用public属性来代替)。
#include <iostream>
#include <cstdlib>
using namespace std;
template<class T>
//定义数据类型,node节点,分别是元素值,本几点高度,指针数组
struct Node {
public:
T x;
int height; // length of next
Node **next;
};
//得到任意的一个数,来初始化节点高度,我选的是30之内,没有依据,但是原则性不要超过32
int pickHeight() {
int z = rand();
//int k = 0;
//int m = 1;
//while ((z & m) != 0) {
// k++;
// m <<= 1;
//}
//return k+1;
cout<<z%30<<endl;
return z%30;
}
//定义跳表类
template<class T>
class skip{
public:
skip();
skip(int);
Node<T> *findPredNode(T );
bool add(T);
bool remove(T);
T find(T);
public:
Node<T> *sentinel;//头结点
int deep;//深度
int number;//节点个数
};
//构造函数
template<class T>
skip<T>::skip(){
this->deep = 1;
this->number = 0;
this->sentinel = new Node<T>();
this->sentinel->x = -1;
this->sentinel->height = 1;
this->sentinel->next = new (Node<T>(*[32]));
for(int i=0;i<32;i++)
this->sentinel->next[i] = NULL;
}
template<class T>
skip<T>::skip(int deep){
this->deep = deep;
this->number = 0;
this->sentinel = new Node<T>();
this->sentinel->x = -1;
this->sentinel->height = deep;
this->sentinel->next = new (Node<T>(*[32]));
for(int i=0;i<32;i++)
this->sentinel->next[i] = NULL;
}
template<class T>
Node<T>* skip<T>::findPredNode(T x) {
Node<T> *u = this->sentinel;
int r = this->deep-1;
while (r >= 0) {
while ( u->next[r] != NULL && (u->next[r]->x - x < 0))
u = u->next[r]; // go right in list r
r--; // go down into list r-1
}
return u;
}
template<class T>
T skip<T>::find(T x) {
Node<T> *u = findPredNode(x);
return u->next[0] == NULL ? NULL : u->next[0]->x;
}
template<class T>
bool skip<T>::remove(T x) {
bool removed = false;
Node<T> *u = this->sentinel;
Node<T> *del = new Node<T>();
int r = this->deep-1;
int comp = 0;
while (r >= 0) {
while (u->next[r] != NULL && ((comp = (u->next[r]->x-x)) < 0))
u = u->next[r];
if (u->next[r] != NULL && comp == 0) {
removed = true;
del = u->next[r];
u->next[r] = u->next[r]->next[r];
if (u == sentinel && u->next[r] == NULL){
this->deep--; // skiplist height has gone down
this->sentinel->height--;
}
}
r--;
}
if (removed) {
delete del;
this->number--;
}
return removed;
}
template<class T>
bool skip<T>::add(T x) {
//get the head ptr
Node<T> *u = this->sentinel;
//define the new node
int r = this->deep-1;
Node<T> *w = new Node<T>();
w->x = x;
w->height = pickHeight();
w->next = new (Node<T>(*[w->height]));
for(int i=0;i<w->height;i++)
w->next[i]=NULL;
//define array storing ptrList
Node<T> **stackList = new (Node<T>(*[32]));
for(int i=0;i<32;i++)
stackList[i] = NULL;
//................................
int comp = 0;
while (r >= 0) {
while (u->next[r] != NULL && ((comp = (u->next[r]->x - x)) < 0))
u = u->next[r];
if (u->next[r] != NULL && comp == 0)
return false;
stackList[r--] = u; // going down, store u
}
int oldDeep = this->deep;
while (oldDeep < w->height)
stackList[oldDeep++] = this->sentinel; // increasing height of skiplist
this->deep = oldDeep;
this->sentinel->height = oldDeep;
this->sentinel->height = oldDeep;
for (int i = 0; i < w->height; i++) {
w->next[i] = stackList[i]->next[i];
stackList[i]->next[i] = w;
}
this->number++;
return true;
}
int main(int argc,char *argv[])
{
skip<int> *test = new skip<int>(2);
test->add(1);
test->add(222);
test->add(12);
test->add(10);
test->add(5);
test->remove(5);
Node<int> *h = test->sentinel;
for(int i=0;i<test->number;i++){
if(h->next[0]!=NULL){
cout<<h->next[0]->x<<" "<<"height is: "<<h->next[0]->height<<endl;
h = h->next[0];
}
}
system("pause");
return 0;
}
4.心得
指针数组的定义
5.结尾
第一次写,写的非常简单,但是代码在visual 2010测试,通过。
浙公网安备 33010602011771号