循环链表
循环链表是指链表中最后那个链结点的指针域存放指向链表最前面哪个结点的指针,整个链表形成了一个环
说明
1.头结点的设置要根据实际需要确定
2.对于采用循环链表作为存储结构的线性表,若链表设置了头结点,则判断空表的条件是
list->link = list
3.对于循环链表,如何判断是否遍历了链表一周?
求非空线性链表的长度
int LENGTH(LinkList list)
{
LinkList p = list;
int n = 0; // 链表初始长度设置 0
while(p!=NULL) {
p = p->link; 非循环链表
n++;
}
return n; // 返回链表的长度n
}
// 循环链表
int LENGTH(LinkList list)
{
LinkList p = list;
int n = 0;
do {
p = p ->link;
n++;
}while(p!=list);
return n;
}
约瑟夫(JOSEPHU)问题
已知n个人(不妨分别以 编号1,2,3,...,n代表)围坐在 一张圆桌周围,编号为k的 人从1开始报数,数到m的那 个人出列,他的下一个人又 从1开始继续报数,数到m的 那个人出列,...,依此重复下 去,直到圆桌周围的人全部 出列。
利用一个不带结点的循环链表
若假设 k = 3 ,m = 4
n :链表中链结点的个数
k:第一个出发点
m:报数
需要做的工作:
1.建立一个不带头结点的循环链表
2.找到第一个触发点
3.反复删除第m个链结点
void JOSEPHU(int n,int k,int m)
{
LinkList list,p,r;
int i;
list = NUll;
for(i = 1;i <=n;i++) {
p = (LinkList)malloc(sizeof(LNode));
p->data = i;
if(list == NULL)
list = p;
else
r->link = p;
}
p ->link = list; // 建立循环链表
p = list;
for(i = 1;i <= k-1;i++) {
r = p;
p = p->link;
}
// 反复寻找并删除结点
while(p->link !=p) {
for (i = 1;i <=m-1;i++) {
r = p;
p = p->link;
}
r->link = p->link;
printf(“%3d”,p->data);
free(p);
p = r->link;
}
pintf(“%3d”,p->data);
}