第二章 线性表(2.5.3-2.6)
2.5.3循环链表
1.定义:
将单链表中的终端结点的指针端由空指针改为指向头节点,就可以使整个链表形成一个环,这种头尾相连的链表称为单循环链表,简称循环链表。
它可以解决一个很麻烦的问题:如何从当中一个结点出发,访问到链表的全部结点
2.循环链表带有空节点的循环链表:

3.非空循环链表:

4.将两个循环链表合并成一个表(使用尾指针):

p=rearA->next;
rearA->next=rearB->next->next;
q=rearB->next;
rearB->next=p;
free(q);
2.5.5双向链表
1.定义
双向链表是在单链表的每个结点中,再设置一个指向其前驱结点的指针域。
所以在双向链表中的结点都有两个指针域,一个指向直接后继,一个指向直接前驱。
/*线性表的双向链表存储结构*/
typedef struct DulNode
{
ElemType data;
struct DuLNode *prior; /*直接前驱指针*/
struct DuLNode *next; /*直接后继指针*/
} DulNode, *DuLinkList;
2.6顺序表和链表的比较
2.6.1空间性能的比较
1.存储空间的分配
顺序表的存储空间需要预先分配,元素个数扩充受一定限制,容易造成存储空间浪费或者空间溢出的现象;而链表不需要预先为其分配空间,只要内存空间允许,链表中的元素个数就没有限制。基于此,当线性表的长度变化较大,难以预估存储规模的时候,最好采用链表作为存储结构。
2.存储密度的大小
链表的每个结点除了设置数据域用来存储数据元素外,还需要额外设置指针域,用来存储指示元素之间逻辑关系的指针,从存储密度上讲,这是不经济的。所谓存储密度是指数据元素本身所占用的存储量和整个结点结构所占用的存储量之比,即
存储密度=数据元素本身所占用的存储量/结点结构所占用的存储量。
存储密度越大存储空间的利用率越高。显然,顺序表的存储密度为1,而链表的存储密度小于1。如果每个元素数据域占用的空间小。例如若单链表的结点数据均为整数,指针所占用的空间和整型量相同,则单链表的存储密度为0.5。因此,如果不考虑顺序表中的空闲区,则顺序表的存储空间的利用率为%100,而单链表的存储空间利用率仅为%50。基于此,当线性表的长度变化不大,易于事先确定其大小时,为了节约存储空间,益采用顺序表作为存储结构。
2.6.2时间性能的比较
1.存取元素的效率
顺序表是由数组实现的,它是一种随机存取的结构,指定任意一个位置序号i,都可以在O(1)时间内直接存取该位置的元素,即取值操作的效率高;而链表是一种顺序存储结构,按位置访问链表第i个元素的时候,只能从表头开始依次向后遍历链表,直到找到第i个位置上的元素,时间复杂度为O(n),即取值操作的效率低。
基于此,若线性表的主要操作是和元素位置紧密相关的这类取值操作,很少做插入和删除时,益采用顺序表作为存储结构。
2.插入和删除操作的效率
对于链表,在确定插入和删除的位置后,插入或删除操作无需移动数据,只需要修改指针,时间复杂度为O(1)。然而对于顺序表,进行插入或删除时,平均需要移动表中近一半的结点,时间复杂度为O(n)。尤其是当某个结点的信息量较大时,移动结点的时间开销就相当客观。
基于此,对于频繁进行插入或删除操作的线性表,益采用链表作为存储结构。
总结:当线性表的长度变化不大时,易于事先确定其大小时,为了节约存储空间,益采用顺序表作为存储结构。
而对于频繁进行插入或删除操作的线性表,益采用链式存储结构。

浙公网安备 33010602011771号