跳跃表原理和实现

跳跃表原理和实现

前提

有时候会被问到链表若是作到二分搜索,可能会有部分的人会去把链表中的值保存到数组来进行二分,可是若是知道跳跃表的话,那么这个数据结构就能够解决这个困惑,它容许快速查询一个有序连续元素的数据链表,它的效率能够作到和二分相同,都是O(logn)的平均时间复杂度,其空间复杂度为O(n)。html

跳跃列表是在不少应用中有可能替代平衡树而做为实现方法的一种数据结构。跳跃列表的算法有同平衡树同样的渐进的预期时间边界,而且更简单、更快速和使用更少的空间。----by 发明者像是redis中有序集合就使用到了跳跃表。web

原理

性质

首先,应该要了解跳跃表的性质;redis

  1. 由不少层结构组成;
  2. 每一层都是一个有序的链表,排列顺序为由高层到底层,都至少包含两个链表节点,分别是前面的head节点和后面的nil节点;
  3. 最底层的链表包含了全部的元素;
  4. 若是一个元素出如今某一层的链表中,那么在该层之下的链表也全都会出现(上一层的元素是当前层的元素的子集);
  5. 链表中的每一个节点都包含两个指针,一个指向同一层的下一个链表节点,另外一个指向下一层的同一个链表节点;

能够看到,这里一共有4层,最上面就是最高层(Level 3),最下面的层就是最底层(Level 0),而后每一列中的链表节点中的值都是相同的,用指针来链接着。跳跃表的层数跟结构中最高节点的高度相同。理想状况下,跳跃表结构中第一层中存在全部的节点,第二层只有一半的节点,并且是均匀间隔,第三层则存在1/4的节点,而且是均匀间隔的,以此类推,这样理想的层数就是logN。算法

搜索

其基本原理就是从最高层的链表节点开始,若是比当前节点要大和比当前层的下一个节点要小,那么则往下找,也就是和当前层的下一层的节点的下一个节点进行比较,以此类推,一直找到最底层的最后一个节点,若是找到则返回,反之则返回空。数组

代码实现大体为:数据结构

find(x)   
{  
    p = top;  
    while (1) {  
        while (p->next->key < x)  
            p = p->next;  
        if (p->down == NULL)   
            return p->next;  
        p = p->down;  
    }  
}  

插入

既然要插入,首先须要肯定插入的层数,这里有不同的方法。1. 看到一些博客写的是抛硬币,只要是正面就累加,直到碰见反面才中止,最后记录正面的次数并将其做为要添加新元素的层;2. 还有就是一些博客里面写的统计几率,先给定一个几率p,产生一个0到1之间的随机数,若是这个随机数小于p,则将高度加1,直到产生的随机数大于几率p才中止,根据给出的结论,当几率为1/2或者是1/4的时候,总体的性能会比较好(其实当p为1/2的时候,也就是抛硬币的方法)。app

当肯定好要插入的层数之后,则须要将元素都插入到从最底层到第k层。ide

删除

在各个层中找到包含指定值的节点,而后将节点从链表中删除便可,若是删除之后只剩下头尾两个节点,则删除这一层。性能

相关文章
相关标签/搜索