漫步数据结构与算法系列之 数组,链表和跳表

数组

 定义数组变量: list = [] (以python举例)

可以是空数组,也可以直接存放初始值。当然也可以存放不同数据类型的元素(泛型)。相对高级一些。数组元素可以重复,集合不可以。(集合会自动给元素去重)

数组查询

数组创建时,会向内存申请一片连续的存储单元(开辟一串连续的存储空间),通过内存管理器来访问存储地址,查询元素。所以访问数组中的第一个元素和任意一个元素,时间和空间的复杂度都是一样的。常数级 O(1)。

我们通过下标(index)随机访问任何一个元素。可见访问时间非常之快。例如: arr[3];查找arr数组中index为3的元素。

增删数组元素(群移操作后且要检查上下界)

移动EFG

ABCEFG是一段连续的存储单元在内存空间中的元素,所谓连续地址是这样0x0001~0x0006,类似如此!

此刻插入元素D。 在index 2 的后面。那么需要提前将index 3~5 整体后移。占据内存空间index 4~6。 存储地址也随之改变(当然需要提前扩容,检查长度)。再把元素D插入进去。

如此可见,数组的插入操作,时间复杂度是O(n)。还是那句话:最坏的情况发生,才是时间复杂度的结果。假如把元素D插入到数组中第一个元素位置,index 为 0 的位置,则数组整体元素从A到G都要平移。所以这是最坏的结果。O(n)

删除也如此,需要移走元素D。 把E~G元素位置整体前移。最后修改下数组长度-1. 因为del一个元素。

链表数据结构(linked list)

链表的出现就是为了弥补数组的缺点: 增删不便。

链表是指物理存储空间上,不连续非顺序的存储结构,就是链表的元素位置不像数组那样呈连续的空间。数据项可以存在不同的内存地址上。

每个数据项都是一个node。每个node都是由data数据部分和指针构成的。每个node都可以通过next指针指向下一个node的位置。末尾的tail的next直接指向空数据项(None)。链表的表头由header表示。(参考下图)

上述是单链表,如果有prev node(前指针),就是双链表。(prev指针可以指向前一个节点node)。既有next,又存在prev node,所以双向链表。

若tail指向header就是循环链表。(环装蛇)

链表结构:表头,node节点和tail尾节点

链表结构

链表的插入:(修改或者调整指针指向就完成了增删改)

调整前继节点next指针,指向插入新元素的节点位置,新元素的next指针指向之前的next node。

新增node节点(插入操作):

linked list 节点插入

删除链表节点(删除操作):

删除节点是插入节点的逆操作。前驱节点的next直接指向删除节点的后一节点。

总结链表的增删查的时间复杂度:

链表的删除和增加操作,不需要引起群移操作,且不需要复制元素(挪元素)所以,时间复杂度是O(1)常数级。(只cut一个节点,在link一个新节点。两步走)

正因为如此,访问链表任意位置并不简单。除了访问head或者tail,是O(1)。若访问链表中间的任意元素,必须从head开始一步步往后移动,才能查到目标节点。所以时间复杂度是O(n)(线性N)

总结:链表除了lookup(随机访问)时间复杂度是O(n);其他增加删除节点都是O(1); 和数组正相反。所以,世界上没有完美的数据结构,都是互补的。完美是优秀的敌人。切记!

链表的优化:跳表(skip list)

对于有序数组,可以用二分查找来,如果有序的链表,如何加速呢?

这里科学家会引入跳表的概念。跳表的数据结构出现的很晚,它对标的是平衡树(AVL Tree)和二分查找。跳表无论插入,删除,搜索都是O(log n)的时间复杂度。参考下图

1. 跳表的使用只能用于有序的链表(链表元素有序)例如下方

跳表用于有序链表

2. 跳表可以加速链表的查询

跳表是通过增加多级索引的过程,类似于升维。 参考下图:比如找链表中的数字8. 首先从最高级索引查找,发现8>7. 所以,锁定下一级索引中的7-9之间。最后在原始表中找到8.

由此可见,第一级索引的步长相当于原始表的2个步长,节点数是n/2;第二级索引是原始表的4个步长,节点数是n/4。依次类推。第k级索引的个数就是 n/(2^k)。 

时间复杂度计算: 总共有h级, 则最高级节点数为2. 那么n/2^h=2; 得到h = (log n)-1; log底数为2.  系数和常数不影响整体时间复杂度。(之前章节有介绍)。则跳表的时间复杂度为O(log n).

总结跳表:跳表将原始的时间复杂度为O(n)的链表,降到了log n, 大大改善了代码的运行效率。例如:原始普通链表有1024个元素,那么需要查询1024次才能完成的查询工作,用跳表log2(1024)=10, 此处2位底数. 只用了10次就完成了查找。

链表升维之后就是跳表

数组,链表,跳表时间复杂度对比总结:

时间复杂度对比

本章小结:

跳表核心思想是链表的升维+空间换时间

数组和链表时间复杂度不同。 所以不同情况使用不同的数据结构。

链表和数组的增删改查方法,在大部分语言中都已经封装好了,可以直接使用,无需再次实现方法。但是实现的过程,还是需要结合代码了解一下。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350