跳表

跳表因为其结构简单,对于一些高效的数据结构红黑树B树等来说相对简单且容易实现。在应用方面也很广泛,比如著名的中间件Redis里面的Zset就用到了跳表来实现高效查询和排序

下面直接上代码

定义结构体

forward[MaxLevel]是一个Node指针类型,用于当前节点指向的下一个节点的指针,为什么是指针数组呢?因为当前节点可能会有好几层索引,其中最顶层跨度最大,越往下跨度越小

struct Node{
	int key;
	Node* forward[MaxLevel];
};

查找算法

大致思路就是:从上层往下找,当当前层的下一个节点比key大,则不能再往后遍历了,需要跳到下一层去比较下一层的下一个节点的值了,直到跳到最底层

举个简单的例子【请叫我灵魂画手_】:

1------------------->5------------------>9---------->11

1------->3-------->5------->7-------->9---------->11

1-->2-->3-->4-->5-->6-->7-->8-->9-->10--->11

  • 当要寻找5,则可以直接1->5 在第一层索引找到

  • 当要找8,则先在第一层跳到5这个位置,然后往下跳,找到7这个位置,再往下跳,找到8

  • 找10,先第一层找到9这个位置,往下跳,找到10

Node* Search(Node* head,int key,int level){
	
	Node* p = head;
	for(int i=level;i>=0;i--){  //从最上层的索引开开始寻找  如果寻找的节点大于值 则跳到下一层寻找 否则遍历下一个节点判断 
		while(p->forward[i]!=NULL && p->forward[i]->key<key){  //当前层数小于要寻找的值 则继续遍历下一个节点 
			p = p->forward[i]; 
		}  
	}
	
	if(p==NULL)
		return NULL;
	if (p->key==key) //当前的节点==key 或者比key小 则没有找到 
		return p;
	else
		return NULL; 	
}

下面看如何插入

插入就是要找到每层的链接点,并且保存连接点,和链表插入思想一样,只是这里多了几个节点而已

//确定高度的随机化算法 
int randX(int &level){
	t = rand()
	for(int i=0,j=2;i<MaxLevel;i++,j+=j){
		if (t>(2/j))
			break
	}
	
	if(i>level){
		level = i //更新最大高度 
	}	
	
	return i; 
} 


void Insert(Node* head,int key,int &level){
	
	Node* p  = head;
	Node* update[MaxLevel];  //临时变量
	
	newLevel = randX(level);
	
	for(int i=level;i>=0;i--){
		
		while(p->forward[i]!=NULL && p->forward[i]->key<key)  //寻找本层的最大节点 
			p = p->forward[i];
		update[i] = p;   //保存本层最大节点 
	}
	
	p = (Node*)malloc(sizeof(Node));
	p->key = key;
	for(int i=0;i<=newLevel;i++){
		p->forward[i] = update[i]->forward[i]; //插入操作
		update[i]->forward[i] = p; 
	}
}

删除:就是插入的逆操作

原文地址:https://www.cnblogs.com/biningooginind/p/12512972.html