m数据结构 day4 线性表List(三) 双链表,循环链表(单向循环 and 双向循环)

单向循环链表 circular linked list 不用头指针,而用尾指针

从单向链表到循环链表:把尾结点指针从空指针改为指向头结点

单链表不能从任意一个节点出发,遍历整个链表,必须从第一个结点开始,因为单链表的结点只存储了指向后继结点的指针,没办法访问到前驱结点。每一次访问都必须从头指针开始遍历,这样访问第一个结点的时间复杂度是O(1),但是访问最后一个结点却是O(n),如果链表很长,那就还比较头疼的。

所以咱们把最后一个元素的指针域不再设置为空指针,而让它指向头结点,单链表就成了一个单向的环,像这样:
在这里插入图片描述
空链表就这样:
在这里插入图片描述

成环后,从任意一个结点出发,都可以访问到整个链表了。

普通单链表看链表是否结束是看指针域是否为空,现在是看指针域是否指向头结点。就这一点差别,没有任何其他改变,从单链表变身循环链表只需要改一下最后一个结点的指针。太简单了有木有。

再到访问首结点和尾结点的时间复杂度都为O(1)的循环链表:撤掉头指针,改用尾指针

单链表和上面的循环链表,访问最后一个结点的时间复杂度都是O(n),(对循环链表,这里说最后一个元素是说出发结点的前一个结点,不是真的尾结点), 访问第一个元素的时间复杂度都是O(1),但是如果使用尾指针,可以使得循环链表中访问第一个结点和最后一个结点的时间复杂度都是O(1)

在这里插入图片描述
在这里插入图片描述

如果要把两个这样的循环链表合并,也是特别简单:
在这里插入图片描述在这里插入图片描述在这里插入图片描述

双向链表 double linked list 每个结点有俩指针域:用空间换时间

双向链表是由单链表扩展来的,他是为了降低访问结点的时间复杂度,所以给每个结点增加一个前驱指针,克服了遍历的单向性,本质是用空间换时间,并且删除插入等操作也需要改两个指针,更加复杂一些。

可见有时候用空间换时间需要的不仅是空间,还需要人的脑力编写更复杂的代码。而时间换空间有时候需要的也不仅是时间,也还需要脑力编写更复杂的代码,比如把递归改为循环的时候,递归代码一般都很简洁,用循环却要长一些。

typedef struct
{
	ElemType data;
	struct DulNode * prior;//结构成员可以是指向自己的指针
	struct DulNode * next;
}DulNode, *DulinkList;//指向双向链表的指针

在这里插入图片描述

插入:四步

在这里插入图片描述

//顺序很重要
s = (DulNode *)malloc(sizeof(DulNode *)); 
s->prior = p;
s->next = p->next;
p->next->prior = s;
p->next = s;

删除:只要两步

在这里插入图片描述

p->prior->next = p->next;
p->next->prior = p->prior;
free(p);//释放结点p的内存

双向循环链表

在这里插入图片描述
在这里插入图片描述在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值