跳表(skip list)的实现
0x00
在《Programming:principle and practice using c++》一书的习题中出现了一个跳表 skip list,第一次听说,百度后大开眼界,是一种顺序查找链表,其查找的时间复杂度为O(logn),插入和删除也为O(logn),Redis中就有用到。原理详见Redis 为什么用跳表而不用平衡树? - 掘金 (juejin.cn)
自己实现了一下,效果如图:
代码如下:
#include "std_facilities.h"
#include "time.h"
#include "stdlib.h"
const int layer=5;
struct Node{
int val;
Node* next;
Node* last;
Node* up;
Node* down;
Node(int v=-1):val{v},next{nullptr},last{nullptr},up{nullptr},down{nullptr}{}
};
struct MList{
vector<Node*> Head{vector<Node*>(layer+1)};
vector<Node*> tail{vector<Node*>(layer+1)};
MList(){
Node* bottom=nullptr;
Node* bottom1=nullptr;
for(int i=0;i<layer+1;i++){
Head[i]=new Node();
tail[i]=new Node();
Node* thisNode=Head[i];
Node* thisNode1=(tail[i]);
thisNode->val=-99999;
thisNode1->val=99999;
thisNode->down=bottom;
thisNode1->down=bottom1;
thisNode->next=thisNode1;
thisNode1->last=thisNode;
if(bottom) bottom->up=thisNode;
if(bottom1) bottom1->up=thisNode1;
bottom=thisNode;
bottom1=thisNode1;
}
}
~MList(){
for(int i=0;i<layer+1;i++){
delete Head[i];
delete tail[i];
}
}
};
void print(Node* l){
while(l){
cout<<l->val<<" ";
l=l->next;
}
cout<<'\n';
}
void print(MList& l){
for(int i=layer;i>=0;i--){
print(l.Head[i]);
}
}
//
Node* findx(MList& l,int val){
Node* p=l.Head[layer];
Node* ret=nullptr;
while(true){
if(val>p->val){
p=p->next;
}else if(val<p->val){
p=p->last->down;
if(p==nullptr) break;
}else{
ret=p;
break;
}
}
return ret;
}
void M_delete(MList& l,int val){
Node* tar=findx(l,val);
if(!tar) error("没有该节点,无法删除\n");
Node* p=tar;
while(p){
Node* t1=p->last;
Node* t2=p->next;
t1->next=t2;
t2->last=t1;
p=p->down;
}
}
void insert(MList& l,Node* n){
Node* pos=nullptr;
Node* p=l.Head[layer];
Node* ret=nullptr;
while(true){
if(n->val>p->val){
p=p->next;
}else if(n->val<p->val){
if(p->last->down)p=p->last->down;
else{
pos=p->last;
break;
}
//if(p==nullptr) break;
}else{
error("已经存在该节点");
}
}
n->next=pos->next;
n->last=pos;
pos->next->last=n;
pos->next=n;
Node* bottom=n;
int maxnum=static_cast<int>(pow(2,layer));
maxnum+=10;
int randint=rand()%maxnum;
int thislayer=1;
cout<<"randint is"<<randint<<'\n';
if(randint==0) thislayer=5;
else if(randint>=1&&randint<3) thislayer=4;
else if(randint>=3&&randint<7) thislayer=3;
else if(randint>=7&&randint<15) thislayer=2;
else thislayer=1;
for(int i=1;i<thislayer+1;i++){
Node* temp=new Node(n->val);
while(true){
if(pos->up){
pos=pos->up;
break;
}else{
pos=pos->last;
}
}
temp->next=pos->next;
temp->last=pos;
pos->next->last=temp;
pos->next=temp;
temp->down=bottom;
bottom->up=temp;
bottom=temp;
}
}
int main(){
time_t t;
srand((unsigned) time(&t));
MList list;
insert(list,new Node(1));
insert(list,new Node(3));
insert(list,new Node(5));
insert(list,new Node(7));
insert(list,new Node(18));
insert(list,new Node(6));
print(list);
Node* x=findx(list,18);
if(x) cout<<"find\n";
else cout<<"no exist\n";
M_delete(list,6);
print(list);
return 0;
}