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测试,通过。

 

posted on 2012-09-07 00:02  不懂自然语言  阅读(121)  评论(0)    收藏  举报