约瑟夫问题(循环链表解法)

约瑟夫问题
由题可知,n个人围成一圈可以画出图来看
在这里插入图片描述
当踢掉一个人的时候,我们就可以将他指向的下一个,给到他前面的人,这样就可以踢掉这个人,就像要将7踢掉,则将6下一个指向8,来将7给跳过,
如图在这里插入图片描述
所以这里我们就可以建立循环链表来实现这个功能。

首先我们先构造结构体指针

#include<stdio.h>
#include<stdlib.h>
int n,k;
typedef struct Clink
{
	int data;
	Clink* next;
}linkcode,*linklist;

然后在初始化循环链表

int initlink(linklist &l)//初始化循环链表 
{
	l=(linklist)malloc(sizeof(linkcode));
	if(!l)
	{
		return 0;
		exit(0);
	}
	l->next=l;//头尾相连
	return 1;
}

在根据n,来判断循环链表的长度,再用尾插法进行赋值

void creattatil(linklist &l)//尾插法给链表赋值 
{	
	l->data=1;
	linklist p=l;
	for(int i=2;i<=n;i++)
	{
		linklist q;
		q=(linklist)malloc(sizeof(linkcode));
		q->data=i;
		p->next=q;
		p=q;
	}
	p->next=l;//最后将尾结点的next指向头节点,来实现头尾相连,形成循环链表。
}

链表构建完毕后,就开始模拟踢人操作

void turnout(linklist &l)
{
	int x=1;//x用来表示第几个人
	linklist p=l;
	linklist q=l;
	while(q->next->next!=l)//将q移动到链表的尾部 ,让q为p的前一项
	{
		q=q->next;
	}
	while(p->next!=p)//如果p->next==p的话,就代表链表中只剩一个元素。 
	{
		if(x%k!=0)//看是数到第几个人,当x是k的倍数时,则当前的人就要被踢掉
		{
			q=p;
			p=p->next;
		}
		else
		{	
			printf("%d ",p->data);
			q->next=p->next;//把q的下一个指向p的下一个,来删除p;
			free(p);
			p=q->next;
		}
		x++;
	}
	printf("%d",p->data);
}
int main()
{
	linklist l;
	scanf("%d%d",&n,&k);//n为多少个人,k为数到k时退出
	if(initlink(l))
	{
		creattatil(l);//尾插法
		turnout(l);//踢人
	}
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值