文章目录
循环链表分为循环单链表和循环双链表。
循环单链表
循环单链表的背景和定义
单链表:
- 表尾结点的
∗
n
e
x
t
*next
∗next指针指向NULL;
循环单链表:
- 表尾结点的 ∗ n e x t *next ∗next指针指向头结点;
循环单链表的初始化
typedf struct LNode{ //定义单链表结构类型
ElemType data; //每个节点存放一个数据元素
struct LNode *next; //指针指向下一个节点
}LNode,*LinkList;
//初始化一个单链表
bool Initlist(LinkList &L){
L = (DNode *) malloc(sizeof(DNode)); //申请一个头结点
if(L==NULL){//内存不足,分配失败
return false;
}
L->next=L;//头结点的next指针指向头结点 ;这个是重点
return true;
}
判断循环单链表是否为空
判断循环单链表只需要将循环单链表的头指针是否指向自己作为判断标准。
bool Empty(LinkList L){
if (L-next==L){
return ture;//头结点下一个指针指向自己;
}
else
return false;
}
在循环单链表中,判断指定结点P是否为表尾结点
我们可以想到:若p结点为表尾结点,它与其他结点不同的是,
p
−
>
n
e
x
t
=
=
L
p->next==L
p−>next==L。
bool isTail(LinkList L,LNode *p){
if(p->next==L){
return ture;
}
else
return false;
}
单链表与循环双链表的区别
单链表:
- 表尾结点的 ∗ n e x t *next ∗next指针指向NULL;
- 从一个结点出发只能找到后续的各个结点;
循环单链表: - 表尾结点的 ∗ n e x t *next ∗next指针指向头结点;
- 从一个结点出发可以找到其他任何一个结点;
- 从尾部找到头部的时间复杂度为 O ( 1 ) O(1) O(1);
循环双链表
循环双链表的背景和定义
双链表:
- 表头结点的 ∗ p r i o r *prior ∗prior指针指向NULL;
- 表尾结点的
∗
n
e
x
t
*next
∗next指针指向NULL;
循环双链表: - 表头结点的 ∗ p r i o r *prior ∗prior指针指向表尾结点;
- 表尾结点的
∗
n
e
x
t
*next
∗next指针指向头结点;
(其实在循环双链表中,所有的 ∗ n e x t *next ∗next指针形成一个闭环,所有的 ∗ p r i o r *prior ∗prior指针也形成一个闭环,)
循环双链表的初始化
typedf struct DNode{ //定义双链表结构类型
ElemType data; //每个节点存放一个数据元素
struct DNode *prior, *next; //前驱和后继指针
}DNode,*DLinkList;
//初始化空的循环双链表
bool InitDLinklist(DLinkList &L){
L = (DNode *) malloc (sizeof(DNode)); //申请一个头结点
if(L==NULL)//内存不足,分配失败;
return false;
L->prior=L;//头结点的前驱指针指向头结点
L->next =L;//头结点的next指针指向头结点
return ture;
}
void testDLinkList (){
//初始化一个双链表
DLinkList L;
InitDLinkList(L);
//....后续代码。。。。。
}
判断循环双链表是否为空
我们思考:循环双链表的判空条件是:头结点的
n
e
x
t
next
next指针是否为其本身。
bool Empty(DlinkList L){
if (L->next==L)
return ture;
else
return false;
}
在循环双链表中,判断指定结点P是否为表尾结点
P结点如果为尾结点必须满足:P结点的next指针指向L ;
bool isTail(DLinkList L,DNode *p){
if(p->next==L){
return ture;
}
else
return false;
}
//发现这与循环单链表的条件一致!
循环双链表的插入
双链表
循环双链表
循环双链表在插入操作的过程中,不需要考虑尾结点插入的特殊情况,而双链表则需要考虑。可以参考我之前的博客《双链表的有关学习以及c语言代码实现基本操作》
《双链表的有关学习以及c语言代码实现基本操作》https://blog.csdn.net/qq_45965736/article/details/126839835
双循环链表的插入操作代码如下:
//函数功能:在p结点之后插入s结点
Bool InsertNextDnode(DNode *p,DNode *s){
s->next =p->next; //1——p结点的后继指针指向赋予s结点的后继指针
p->next->prior=s; //2-p结点的后继指针的前驱指针指向s
s->prior=p; //3-s结点的前向指针指向p
p->next=s; //4-p结点的后继指针指向s
//1和2两步必须在4之前
循环双链表的删除
循环双链表在删除操作的过程中,同样也不需要考虑删除结点时是尾结点的特殊情况,而双链表则需要考虑。可以参考我之前的博客:《双链表的有关学习以及c语言代码实现基本操作》
《双链表的有关学习以及c语言代码实现基本操作》https://blog.csdn.net/qq_45965736/article/details/126839835
双循环链表的删除操作代码如下:
//函数功能:在p结点之后插入s结点
Bool InsertNextDnode(DNode *p,DNode *s){
s->next =p->next; //1——p结点的后继指针指向赋予s结点的后继指针
p->next->prior=s; //2-p结点的后继指针的前驱指针指向s
s->prior=p; //3-s结点的前向指针指向p
p->next=s; //4-p结点的后继指针指向s
//1和2两步必须在4之前