循环链表
在单链表中,每个结点都带有一个指向其后继结点的指针,但因为表尾元素没有后继结点,所以表尾结点的指针域为空,表明它不指向任何结点,并表示这个结点是最后一个结点。
现在修改这个约定,将表尾结点的指针指回头结点,从而形成一类新链表。在这样的链表中,从任何一个结点出发并沿着指针域的指示,可以回到这个结点,好像转了一个圈,可以将这样的链表称为循环链表,更准确地说,它是单向循环链表。
在带头结点的单链表中,表为空的判断条件是“head->next == null”,而在循环链表中,表为空的判断条件是“head->next==head”。
双向链表
在单链表中,每个结点都仅含有一个指针,除表尾结点以外,该指针指向后继节点,故超找后继节点的操作很方便。从插入及删除操作的实现步骤中可以了解到,查找前驱结点很不方便。
在表结点中,除保留指向后继结点的指针以外,在增加一个指向该结点的前驱结点的指针,即每个结点都含有两个指针,一个指向该结点的后继结点,另一个指向该结点的前驱结点。如果结点的前驱结点或后继结点不存在,则相应的指针为空。这样的链表称为双向链表,也称双链表。
顺序表与链表的比较
- 顺序表存储每个元素时,空间比较紧凑,占用空间连续
- 顺序表数组的每个单元只需保存数据本身,没有额外的开销。(链表有前后指针)
- 顺序表初始化的时候,通常要“宽松”一些,当线性表中元素个数没有达到顺序表的最大容量时,数组中仍然会有空闲的空间,此时并没有充分利用全部空间。
- 链表中的占用空间大小与链表中的元素个数成正比,分配的节点是全部被使用的。当线性表的元素个数相对较少时,链表的实现比顺序表的实现更节省空间。
- 选择顺序表或链表的一个因素是,当线性表中的元素个数变化较大或未知时,最好使用链表实现,如果知道线性表的大致长度,则使用顺序表时占用的空间效率会更高。
- 时间效率。以访问线性表的第i个元素为例,在顺序表中是直接定位的,可以实现随机访问,操作的时间复杂度是O(1)。相比之下,单链表不能随机访问指定的元素,访问时必须从表头开始逐个查找,直到找到第i个结点为止。这个操作的平均时间复杂度和最差时间复杂度均为O(n)。关于插入和删除操作,在给出指向链表合适位置的当前指针后,在单链表内进行插入和删除的时间复杂度可以达到O(1)。而顺序表的插入时间复杂度均为O(n)。对应线性表的许多应用,插入和删除都是主要操作,因此它们的时间效率非常重要,仅对此而言,单链表通常比顺序表更灵活。