首先为了方便,我大概在博友林子的博客基础上进行编辑,今天我将跳跃表实现了一下,算法导论公开课的那位年轻教授说他花了半个小时写好半个小时调试好,我的时间估计是他的4倍吧,只有结构实现看了这篇博客的插入代码,了解了只需要在n空间大小构建跳跃表的结构。对于自己几乎独立的实现了这个算法,虽然简单,但是还是很有成就感的。需要自己注意的是在独立实现代码的时候不仅仅只是需要简单的了解大概的算法,而是
1)确定需要使用的数据结构,如今天的代码中的SKNode, SkipList.
2)如何初始化这个数据结构,这样才能得到求解问题循环结束条件。(初始化条件很重要)
3)先自己按照算法流程,插入、查找、删除一个一个写好伪代码,这样才不至于在写代码的时候没有关注点,思维混乱。可以先从最简单也是最和核心的查找算法写起。
4)最后是调试,碰到不对的步骤,可以添加打印,我现在对于数据结构还有太底层的调试时看不出来太多信息的,只能一步一步的试探。这也是一个软肋,以后有空一定要再学学编程范式这种比较底层的东西,还有内存管理也很重要。
参考的博文地址如:
http://blog.csdn.net/u013011841/article/details/39158585
跳跃链表简介
二叉树是一种常见的数据结构。它支持包括查找、插入、删除等一系列操作。但它有一个致命的弱点,就是当数据的随机性不够时,会导致其树形结构的不平衡,从而直接影响算法的效率。
跳跃链表(Skip List)是1987年才诞生的一种崭新的数据结构,它在进行查找、插入、删除等操作时的期望时间复杂度均为O(logn),有着近乎替代平衡树的本领。而且最重要的一点,就是它的编程复杂度较同类的AVL树,红黑树等要低得多,这使得其无论是在理解还是在推广性上,都有着十分明显的优势。
跳跃链表的最大优势在于无论是查找、插入和删除都是O(logn),不过由于跳跃链表的操作是基于概率形成的,那么它操作复杂度大于O(logn)的概率为,可以看出当n越大的时候失败的概率越小。
另外跳跃链表的实现也十分简单,在平衡树中是最易实现的一种结构。例如像复杂的红黑树,你很难在不依靠工具书的帮助下实现该算法,但是跳跃链表不一样,你可以很容易在半个小时内就完成其实现。
跳跃链表的空间复杂度的期望为O(n),链表的层数期望为O(logn).
如何改进普通的链表?
我们先看看一个普通的链表
可以看出查询这个链表O(n),插入和删除也是O(n).因此链表这种结构虽然节省空间,但是效率不高,那有没有什么办法可以改进呢?
我们可以增加一条链表做为快速通道。这样我们使用均匀分布,从图中可以看出L1层充当L0层的快速通道,底层的结点每隔固定的几个结点出现在上面一层。
我们这里主要以查找操作来介绍,因为插入和删除操作主要的复杂度也是取决于查找,那么两条链表查找的最好的时间复杂度是多少呢?
一次查找操作首先要在上层遍历<=|L1|次操作,然后在下层遍历<=(L0/L1)次操作,至多要经历
次操作,其中|L1|为L1的长度,n为L0的长度.
那么最好的时间复杂度,也就怎么设置间隔距离才能使查找次数最少有
我们对|L1|的长度求导得
把上式代入函数,查找次数最小也就是.这意味着下层每隔个结点在上层就有一个结点作为快速跑道。
那么三条链表呢
同理那么我们让L2/L1=L1/L0,然后同样列出方程,求导可得L2=,查找次数为3*
………………………………………………………………
第k条链条…..查找次数为
我们这里取k=logn,代入的查找次数为2logn.
到此为主,我们应该知道了,期望上最好的层数是logn层,而且上下层结点数比为2,这样查找次数常数最小,复杂度保持在O(logn)。
跳跃链表的结构
跳跃表由多条链构成(L0,L1,L2 ……,Lh),且满足如下三个条件:
每条链必须包含两个特殊元素:+∞ 和 -∞(可以需要,可以不需要,我的实现是采用了-∞作为header之后的 节点,即第一个节点,+∞作为最后一个节点)
L0包含所有的元素,并且所有链中的元素按照升序排列。
每条链中的元素集合必须包含于序数较小的链的元素集合。
结点结构源代码
我觉得如果不考虑空间效率是可以将数据在每层上面分开存储,但是也可以办到在一个n的空间存储,跳跃表就是在这些数据之间建立links,使用links替代树形结构,如Btreap树堆,R-B Trees, AVL trees。 现在我给的是基于一个n空间存储。
[cpp] view plain copy
class SKNode
{
public:
int key;
SKNode* forward[MAXLEVEL];
SKNode()
{
key=0;
for(int i =0;i<MAXLEVEL;i++)
{
forward[i]= NULL;
}
}
SKNode& operator=(const SKNode* & node)
{
key=node->key;
for(int i=0;i<MAXLEVEL;i++)
{
forward[i] = node->forward[i];
}
return *this;
}
};
//skip list, it has a header, this header have maxlevel pointers
class SkipList
{
public:
SKNode hdr; / list Header */
int listLevel; /* current level of list */
int insert(int key);
SKNode* search(int key);
int deleteNode(int key);
void printList();
SkipList()
{
hdr = new SKNode;
listLevel = 0;
hdr->key = -INT_MAX;
SKNode* end = new SKNode;
SKNode* first = new SKNode;
first->key=-INT_MAX;
end->key=INT_MAX;
for(int i =0;i
include
include
using namespace std;
define MAXLEVEL 4 //最多2 power n=16个数
/skip list node,they are keys and pointers/
classSKNode
{
public:
int key;
SKNode* forward[MAXLEVEL];
SKNode()
{
key=0;
for(inti =0;i