约瑟夫问题(环形链表) C语言

**有n个人围成一圈,顺序排号,从第一个开始报数(从1到3报数),凡报到3的人退出圈子,问最后最后留下的是原来第几号的那位. **

约瑟夫问题
基于环形链表实现

这里要注意的是
代码中的变量k用来记录现在报的数
当k为2时,则说明下一个人报数3,释放下一个人的空间(把下一个人踢出队列),若等到k为3再释放,还要记录上一个人的next的指向,指向k为3的next,所以在k=2时就处理,会比较方便

编号从一开始
输入总人数
输出最后留下的那个人的编号
具体解释已在代码注释中给出,若有不懂,可以评论区留言或者私信,我会尽快回复的。

#include 
#include 
typedef struct node  //定义链表
{
	int number;   //存储每个人的编号,从1开始
	struct node* next;
}Link,*PLink;
int yue(int n);     //判断约瑟夫问题最后的答案
int main()
{
	int n;
	printf("请输入人数:");
	scanf("%d", &n);
	printf("最后留下的人是:%d\n", yue(n));

	return 0;
}
int yue(int n)
{
	PLink head = NULL;   //头指针
	PLink p = NULL, q = NULL;   //建链表辅助指针
	for (int i = 0; i < n; i++)
	{
		q = (PLink)malloc(sizeof(Link));  //申请新的空间
		q->number = i + 1;
		q->next = NULL;
		if (head == NULL)
			head = q;   //头指针为空,则给头指针指向申请的空间
		else
			p->next = q;
		p = q;   //保留此次循环申请的空间
	}
	p->next = head; //结尾next指向头部,组成环形链表
	int k = 0;
	//int j = 7;
	while (1)
	{
		if (head->next == head)   //当环形链表只剩一个元素时,结束循环
			break;	
		k++;
		if (k == 2)    //当k为2时,则说明下一个人报数3,释放下一个人的空间,若等到k为3再释放,情况会较麻烦
		{
			printf("%d\n", head->next->number);  //打印出出列的人
			q = head->next; 
			head->next = head->next->next;  //next直接指向下下个元素
			free(q);   //释放下一个元素
			k = 0;
		}
		head = head->next;
	}
	return head->number;   //返回最后剩下的那个人的编号
}

运行截图:
约瑟夫问题(环形链表) C语言_第1张图片

你可能感兴趣的:(c语言,链表,c语言,数据结构)