循环链表是另一种形式的链式存储结构形式。
- 循环单链表:将表中尾结点的指针域改为指向表头结点,整个链表形成一个环。由此从表中任一结点出发均可找到链表中其他结点。结点类型与非循环单链表的相同。
- 循环双链表:形成两个环。结点类型与非循环双链表的相同。
1.循环单链表
(图片来自中国大学MOOC)
与非循环单链表相比,循环单链表:
- 链表中没有空指针域
- p所指结点是尾结点的条件:
p->next==L
2.循环双链表
(图片来自中国大学MOOC)
与非循环双链表相比,循环双链表:
- 链表中没有空指针域
- p所指结点为尾结点的条件:
p->next==L
- 一步操作即L->prior可以找到尾结点
看一个例子:
问题描述: 设计判断带头结点的循环双链表L(含两个以上的结点)是否对称相等的算法。
算法思路:
- 设置两个数据结点p和q,p从左向右扫描链表
L
,q从右向左扫描链表L
- 若p和q对应的
data
域不相等,则退出循环,说明该链表不对称 - 否则继续比较,直到p与q相等(数据结点个数为奇数)或p的下一个结点为
*q
(数据结点为偶数)为止
代码实现:
#include<stdio.h>
#include<stdlib.h>
#define MaxSize 100
typedef int ElemType;
typedef struct DNode *DLinkList;
typedef struct DNode//定义链表
{
ElemType data;
DLinkList next, prior;
};
void CreateList(DLinkList &L, ElemType a[], int n)//创建链表
{
L = (DLinkList)malloc(sizeof(DLinkList));
int i;
DLinkList s = NULL, r = NULL;
L->next = L;
L->prior = L;
r = L;
for (i = 0; i < n; i++)
{
s= (DLinkList)malloc(sizeof(DLinkList));
s->data = a[i];
s->prior = r;
s->next = L;
r->next = s;
L->prior = s;
r = s;
}
}
void PrintList(DLinkList L)//打印链表
{
DLinkList p=L->next;
printf("形成的链表如下:\n");
while (p != L)
{
printf("%d", p->data);
p = p->next;
}
printf("\n");
}
int Fact(DLinkList L)//判断是否对称
{
int flag=1;
DLinkList p,q;
p=L->next;q=L->prior;
while(flag==1)
{
if(p->data!=q->data)
{
flag=0;
}
else
{
if(p==q||p==q->prior)
{
break;
}
p=p->next;
q=q->prior;
}
}
return flag;
}
int main()
{
int n, i,flag=0;
ElemType a[MaxSize];
DLinkList L;
printf("输入链表的长度:\n");
scanf("%d", &n);
printf("输入元素:\n");
for (i = 0; i < n; i++)
{
scanf("%d", &a[i]);
}
CreateList(L, a, n);
PrintList(L);
flag=Fact(L);
if(flag==1)
{
printf("该循环双链表对称");
}
else
{
printf("该循环双链表不对称");
}
return 0;
}
以上为本人学习后的笔记,方便复习,资源来自中国大学MOOC,如有错误请指出。