zoukankan      html  css  js  c++  java
  • 跳表

    1、对于一个单链表来讲,即便链表中存储的数据是有序的,要想在其中查找某个数据,也只能从头到尾遍历链表。这样查找效率就会很低,时间复杂度会很高,是 O(n),可以每几个结点提取一个结点到上一级(把抽出来的这一级叫作索引或索引层),这种加多级索引的链表结构,就是跳表
    2、如果要在有序链表查找某个结点,比如 16。我们可以先在索引层遍历,假设当遍历到索引层中值为 13 的结点时,我们发现下一个结点是 17,那要查找的结点 16 肯定就在这两个结点之间。然后我们通过索引层结点的 down 指针,下降到原始链表这一层,继续遍历找到16
    3、跳表的时间复杂度O(logn);每m个结点抽出一个结点作为上一级索引的结点,假设索引有 h 级,可以得到 n/(2^h)=m,从而求得 h=log2n-1,包含原始链表这一层,整个跳表的高度就是 log2n。如果每一层都要遍历 m 个结才能找到数据,那在跳表中查询一个数据的时间复杂度就是 O(m*logn),即O(logn)
    4、跳表的空间复杂度
    4.1、每2个结点抽出一个结点作为上一级索引的结点,假设原始链表大小为 n,那第一级索引大约有 n/2 个结点,第二级索引大约有 n/4 个结点,以此类推,每上升一级就减少一半,直到剩下 2 个结点,这几级索引的结点总和就是 n/2+n/4+n/8…+8+4+2=n-2。所以,跳表的空间复杂度是 O(n)
    4.2、每3个结点抽出一个结点作为上一级索引的结点,总的索引结点大约就是 n/3+n/9+n/27+…+9+3+1=n/2。尽管空间复杂度还是 O(n),但比上面的每两个结点抽一个结点的索引构建方法,要减少了一半的索引结点存储空间
    4.3、在实际的软件开发中,原始链表中存储的有可能是很大的对象,而跳表索引结点只需要存储关键值和几个指针,并不需要存储对象,所以当对象比索引结点大很多时,跳表索引占用的额外空间就可以忽略了
    5、由于在跳表中查询某一个数据的时间复杂度O(logn),所以动态插入和删除都很高效
    6、当我们不停地往跳表中插入数据时,如果我们不更新索引,就有可能出现索引层某2个索引结点之间数据非常多的情况。极端情况下,跳表还会退化成单链表。可同过相应地增加索引结点(通过随机函数的方法)来避免复杂度退化,以及查找、插入、删除操作性能下降
    6.1、当我们往跳表原始链表中插入数据的时候,我们可以选择同时将这个数据插入到部分索引层中,我们通过一个随机函数,来决定将这个结点插入到哪几级索引中,比如随机函数生成了值 K,那我们就将这个结点添加到第一级到第 K 级这 K 级索引中
    6.2、红黑树、AVL 树这样平衡二叉树是通过左右旋的方式保持左右子树的大小平衡

  • 相关阅读:
    第一章epoll
    sk_buff结构--转载
    邻居子系统1.5 neigh output
    netfilter内核态与用户态 通信 之 sockopt
    邻居子系统1.4
    邻居子系统 1.3
    邻居子系统 1.2
    邻居子系统 1.1
    linux 内核 tasklets 原理以及工作队列
    linux 内核 同步原理
  • 原文地址:https://www.cnblogs.com/jetqiu/p/13358357.html
Copyright © 2011-2022 走看看