约瑟夫环问题链表实现

问题描述:约瑟夫环问题是,编号为1,2,3,…,n的n个人按顺时针方向围坐一圈,每人持有一个密码。开始时任选一个正整数作为报数上限值m,从第一个人开始顺时针方向自1开始顺序报数,报到m时停止报数。报m的人出列,将他的密码作为新的m值,从他在顺时针方向上的下一个人开始重新从1报数,如此下去,直至所有人全部出列为止。

基本要求:利用单链表存储结构模拟此问题,按照出列顺序打印各人的编号。

测试数据:M的初值为20,n=7,7个人的密码依次为3,1,7,2,4,8,4。则首先出列的人是6号,依次正确的出列顺序应该为6,1,4,7,2,3,5。

实现提示:要求用户指定报数上限值,然后读取每人的密码。此问题所用循环链表不需要头结点。

实现思路:构造一个循环链表,通过循环始终将一个指针指向第m个人的直接前驱,更新密码m,修改链表

#include<stdio.h>
#include<malloc.h> 
#define LEN sizeof(struct Node) 
struct Node
{
	int num;								//编号 
	int code;								//密码 
	struct Node *next;
};
//创建长度为n单向循环链表
struct Node *creat(int n)
{
	int i=1;
	struct Node *p,*q,*head;
	p=(struct Node*)malloc(LEN);
	for(i=1;i<=n;i++)
	{
		if(i==1)
			head=p;				//头指针 
		else
		{
			q=(struct Node*)malloc(LEN);
			p->next=q; 
			p=q;	
		}	
		p->num=i;
		scanf("%d",&p->code);		//依次输入密码 
	}
	p->next=head;
	return head;
}
//输出出列人的编号
void joseph(struct Node *head,int m)
{
	struct Node *p,*q;
	q=head;
	//head的前驱初始化为 q,
	while(q->next!=head)
			q=q->next;
		p=head;					//p指向 head 
	//链表中超过一个结点 
	while(p->next!=p)
	{
		//p指向要出列的人,q的后继指向p 
		for(int i=1;i<m;i++)
		{
			p=p->next;
			q=q->next;
		}
		printf("%d ",p->num);
		m=p->code;
		q->next=p->next;
		p=p->next;
	}
	//链表中只剩余一个结点,输出 
	if(p->next==p)
		printf("%d ",p->num);
}
int main()
{
	struct Node *head;
	int M,n;
	printf("输入链表长度 n 和 M 的初始值:\n");
	scanf("%d%d",&n,&M);
	printf("依次输入 %d 个人的密码:\n",n);
	head=creat(n);				//建立链表 
	printf("出列的人依次为:\n");
	joseph(head,M);				//依次输出出列人员编号 
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值