什么是循环链表?
链表头尾相连,将链表的最后一个节点的指针域指向他的头节点,形成一个环状,这就叫循环链表。
什么是瑟夫环问题?
约瑟夫环问题,是一个经典的循环链表问题,题意是:已知 n 个人(以编号1,2,3,…,n分别表示)围坐在一张圆桌周围,从编号为 k 的人开始顺时针报数,数到 m 的那个人出列;他的下一个人又从 1 还是顺时针开始报数,数到 m 的那个人又出列;依次重复下去,要求找到最后出列的那个人。
循环链表实现很简单,接下来我们来实际应用到瑟夫环问题中,链表第一步,首先创建一个结构体
#include <stdio.h>
#include <stdlib.h>
//这里不过多解释了
typedef struct node
{
int data;
struct node *next;
}link;
复制代码
初始化链表
link *initCyclic(int n)
{
int i;
link * head=(link*)malloc(sizeof(link));//申请空间 定义头部节点数据
head->data=1;
head->next=NULL;
link * cyclic=head;//创建一个指针 不至于丢失头地址
for (i=2; i<=n; i++) {
link * body=(link*)malloc(sizeof(link));
body->data=i;
body->next=NULL;
cyclic->next=body;
cyclic=cyclic->next;
}
cyclic->next=head;//这里首尾相连,这样就形成一个环。
return head;
}
复制代码
实际应用到瑟夫环问题上
void circulation(link *head,int k,int m)
{
link *tail;
link *p = head;
int i = 1;
while (p->data != k) {//k是开始报数的人,这里找到k的指针地址
tail = p;
p = p->next;
}
while (p->next != p) {//从k开始发言
for (i=1;i<m;i++) {//判断数到m的人出列
tail = p;//出列者的上一个节点
p = p->next;//出列者的指针
}
tail->next = p->next;//将上一个节点的指针域改成下个节点的指针域
printf("出列人的编号为:%d\n", p->data);
free(p);//释放内存
p = tail->next;
}
printf("出列人的编号为:%d\n",p->data);
free(p);
}
复制代码
开始运行
int main() {
printf("输入圆桌上的人数n:");
int n;
scanf("%d",&n);
link * head=initCyclic(n);
printf("从第k人开始报数:");
int k;
scanf("%d",&k);
printf("数到m的人出列:");
int m;
scanf("%d",&m);
circulation(head, k, m);
return 0;
}
复制代码