三种链表的介绍
原谅我拙劣的绘图能力,花了半天终于还是决定从网上找来了这三张图,因为环形链表的弧形箭头难以完美的展现出来。
以下3张图片来自Wikipedia。
大家看着图片应该也都知道这分别是哪种链表了。那么链表到底是什么呢?
它和前面的栈和队列一般,都是基本的数据结构,其中的各个对象按线性顺序排列。大家应该注意到了图中的大黑点,有些C/C++编程基础的同学肯定能够猜到链表是通过各个对象里的指针来指向下一个对象的,相比,数组则是通过下标来进行索引。
为了让大家加深印象,我们来联系到生活中的实例。
首先是单向链表(singly linked),我第一个联想到的就是下面这种铅笔,满满的儿时回忆呀!找了好久才找到这张图,却不知道它的名字。
然后是双向链表(doublely linked list),动车组则可以很好的诠释它。
循环链表(circular linked list)的应用是比较多的,从小接触的自行车链条就是其中之一。
大家要是还有什么例子欢迎在评论中留下哦。
链表是如何指引的
单链表
前面已经说到了,链表通过指针来指向下一个对象。单链表中有一个关键字key和指针next,当然了,对象中还可以有其他的卫星数据。我们可以这样想象它,前面的图中是一行对吧,然后在行中的链表节点中向下延伸,每个节点都延伸成一列,简单的说,从一维变成了二维(类比二维数组)。
将链表中的一个元素设为x,那么x.key就是它的值,x.next就是链表中的后继元素。如果x.next=NIL,那么就说明没有后继元素了,因此x就是链表的尾(tail)。
双向链表
将单链表升级到双向链表来考虑,无非就是多了一个前驱,用x.prev来表示。同样的,x.prev=NIL,表示没有前驱,那么x就是链表的头(head)。而如果头都为空了,那么整个链表也就是空的了。
循环链表
相应的,循环链表也由双向链表升级而来,就是将链表尾部的元素x的next指向链表的头部y,元素头部的元素y的prev指向链表的尾部x。
链表的搜索、插入、删除
搜索
我们的目的是要搜索出链表L中第一个关键字为k的元素,函数返回的将是指向该元素的指针。
如果不幸的是链表中不存在这个元素,那么就返回NIL。
LIST-SEARCH(L,k)
1 x=L.head
2 while x!=NIL and x.key!=k
3 x=x.next
4 return x
由于这个搜索是线性的,在最坏的情况下它会搜索整个链表,因此该情况下LIST-SEARCH的运行时间为