第3章:4.循环链表和双向链表

本篇文章参考的是《大话数据结构》,感谢作者程杰先生。

一:循环链表:
将单链表中终端节点的指针端由空指针改为指向头结点,就使整个单链表形成了一个环,
这种头尾相接的单链表称为单循环链表,简称循环链表(circular linked list)。

图示:
在这里插入图片描述
二: 将下面两个单循环链表合并:

在这里插入图片描述
过程如下:

p = rearA->next;					// 保存A表的头结点,即① 
rearA->next = rearB->next->next;	//将本是指向B表的第一个节点(不是头结点),赋值给 rearA->next,即② 
rearB->next = p;					//将原A表的头结点赋值给 rearB->next,即③ 

free(p);							//释放p

三:双向链表(double linked list):
在单链表的每个节点中,再设置一个指向其前驱结点的指针。所以在双向链表中的结点都有两个指针域,
一个指向直接后继,一个指向直接前驱。

/*线性表的双向链表存储结构*/
typedef struct DulNode
{
    
    
		ElemType data;
		struct DuLNode *prior;    	/*直接前驱指针*/
		struct DuLNode *next;		/*直接后继指针*/
} DulNode, *DuLinkList;

四:非空的循环的带头结点的双向链表如下所示:
在这里插入图片描述
就像人生一样,想享乐就得先努力,欲收获就得付出代价。
双向链表既然比单链表多了反向遍历查找等数据结构,就得付出一些代价,
在插入和删除时,需要改变两个指针变量。

五: 双链表的插入:
插入操作并不复杂,但是顺序很重要,绝对不能写错了。

假设存储元素e的结点为s,要实现将结点s插入到结点p和p->next之间需要如下几步:
在这里插入图片描述

总共分四步:

s->prior 		= p;		//把p赋值给s的前驱,如图中1
s->next 		= p->next;	//把p->next赋值给s的后继,如图中2
p->next->prior 	= s;		//把s赋值给p->next的前驱,如图中3
p-next 			= s;		//把s赋值给p的后继,如图中4

技巧1:赋值的顺序(双臂伸缩法)
1.展开左手臂;
2.展开右手臂;
3.收回右手臂;
4.收回左手臂;
刚好对应上图的4条箭头指向。

技巧2:每一步的赋值(看箭头指向)
A -----------------------------------------------------------------> B
A的前驱/后继(取决于箭头从A的那个位置开始) = B(直接写该结点的标识);

六:双链表的删除:
要删除结点p,只需要如下两步:
在这里插入图片描述
总共分三步:

p->prior->next = p->next;	//把p->next赋值给p->prior的后继,如图1
p->next->prior = p->prior;	//把p->prior赋值给p->next的前驱,如图2

free(p);					//释放节点p

注:
1.删除的顺序是先上后下(箭头);
2.对于删除来说技巧2同样适用;

猜你喜欢

转载自blog.csdn.net/yanghangwww/article/details/110305261