数据结构 & 跳表|青训营笔记

105 阅读3分钟

这是我参与「第四届青训营 」笔记创作活动的第[6]天

跳表

  • 假如有一个单链表,如果是想要查找某个数据,那么只能从头遍历到尾,因为链表不支持随机访问,查找的效率就很低,时间复杂度也是为O(n)。
  • 如果是想要提高查找的效率,那么可以在建立一个一级索引
    •    1   -->>  4  -->>   7  -->>   9   -->>   13   -->>   16  -->>    19   -->>   23
         |         |         |         |          |           |           |           |     
         |         |         |         |          |           |           |           |
         1 -> 3 -> 4 -> 5 -> 7 -> 8 -> 9 -> 10 -> 13 -> 14 -> 16 -> 17 -> 19 -> 21 -> 23 -> 24 -> 25
      
    • 当查找5的时候,从索引层出发,如果当下一个节点的索引的值大于查找的值时候,那么可以去下一层查找,直到找到值。
    • 当查找21的时候,只需要遍历8个节点,原来需要遍历14个节点。遍历的节点个数减少了,那么查找的效率也高了起来。
  • 可以建立一个一级索引,那么肯定是可以建立一个二级的索引,当建立了一个二级索引时:
    •   1     ---->>>>      7      ---->>>>      13       ---->>>>       19
        |                   |                    |                       |           
        |                   |                    |                       |
        1   -->>  4  -->>   7  -->>   9   -->>   13   -->>   16  -->>    19   -->>   23
        |         |         |         |          |           |           |           |     
        |         |         |         |          |           |           |           |
        1 -> 3 -> 4 -> 5 -> 7 -> 8 -> 9 -> 10 -> 13 -> 14 -> 16 -> 17 -> 19 -> 21 -> 23 -> 24 -> 25
      
    • 再次查找21的时候,需要遍历5个节点,而一级索引需要8个节点,单链表的形式而需要14个节点,如果数据量更大,那么查找的效率会快很多,提升也是很明显的。

跳表的时间复杂度 & 空间复杂度

  • 时间复杂度
    • 假如链表中有n个节点,那么一级索引的节点个个数为n/2,二级索引的节点个数为n/4,三级所以的节点个数为n/8,那么第m级索引的节点个数为nn/(22 m^m)。
    • 假如最高级的索引有2个节点,那么可以得到nn/(22 m^m)=2,从而求得m=log2log2n-1,包含了原始链表这一层的话,整个跳表的高度就是log2log2n层。
    • 在每一层都需要遍历k个节点,那么查找一个数据的时间复杂度为O(m*lognlogn)。
    • 需要查找一个数据x时,在第k级索引中,遍历到了y节点之后,发现x大于y,小于后面的节点z,所以需要下降到第k-1级索引,在第k-1级索引中,y和z之间只有3个节点,所以每一级都最多遍历3个节点。
    • 那么就为O(3*lognlogn),所以跳表查询任意数据的时间复杂度就是O(lognlogn)。这个时间和二分查找一样,基于单链表实现了二分查找。
    • 从单链表的增加O(n) 删除O(n) 修改O(n) 查找O(n)的时间复杂度 ==>> 到跳表的增加O(lognlogn) 删除O(lognlogn) 修改O(lognlogn) 查找O(lognlogn)的时间复杂度
  • 空间复杂度
    • 链表中的n个节点,一级索引的节点个数为n/2,二级索引的节点个数为n/4,三级索引的节点个数为n/8。
    • 那么就是n/2 + n/4 + n/8.... + 8 + 4 + 2=n-2,所以跳表的空间复杂度是O(n)。

维护跳表

  • 当一直在跳表两个节点中执行插入操作时,跳表还会退化成单链表,那么需要维护索引与原始链表大小之间的平衡。
  • 当链表中的节点多了,索引节点就增加一些,避免退化成单链表