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

约瑟夫问题
由题可知,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);//踢人
	}
}
  • 9
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
约瑟夫问题是一个经典的算法问题,假设有n个人围成一圈,编号从1到n,从第1个人开始报数,报到第m个人出列,然后从出列的下一个人开始重新报数,直到所有人都出列为止。请使用循环链表实现这个算法。 首先,我们需要定义一个节点类,表示每个人的信息和位置。节点类包含两个属性,一个是编号,另一个是指向下一个节点的指针。 ```python class Node: def __init__(self, data): self.data = data self.next = None ``` 然后,我们需要构造循环链表,将所有人的信息存储在链表中。为了方便起见,我们可以先构造一个单向链表,然后将链表的尾节点指向头节点,形成一个循环链表。 ```python def construct_circle_list(n): head = Node(1) cur = head for i in range(2, n+1): new_node = Node(i) cur.next = new_node cur = new_node cur.next = head return head ``` 接下来,我们需要实现约瑟夫问题解法。我们可以使用一个计数器count,表示当前报数的人的位置,当count等于m时,将该节点从链表中删除。具体实现如下: ```python def josephus(head, m): cur = head while cur.next != cur: count = 1 while count < m-1: cur = cur.next count += 1 print("出列的人的编号为:", cur.next.data) cur.next = cur.next.next cur = cur.next print("出列的人的编号为:", cur.data) ``` 最后,我们可以在主函数中调用上述函数,解决约瑟夫问题。 ```python if __name__ == '__main__': n = 10 m = 3 head = construct_circle_list(n) josephus(head, m) ``` 上述代码的输出结果为: ``` 出列的人的编号为: 3 出列的人的编号为: 6 出列的人的编号为: 9 出列的人的编号为: 2 出列的人的编号为: 7 出列的人的编号为: 1 出列的人的编号为: 8 出列的人的编号为: 5 出列的人的编号为: 10 出列的人的编号为: 4 ``` 这个结果符合我们的预期,表示最后出列的顺序为3、6、9、2、7、1、8、5、10、4。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值