约瑟夫出圈问题

今天介绍约瑟夫出圈问题,关于问题的介绍如下:在这里插入图片描述
为了证明约瑟夫的选择是正确的,我们可以想办法用代码来模拟这个过程。
下面是模拟过程:
1.如何模拟这41个人?
因为我们的目的是为了找到最后存活下来的两个人的位置,所以对于每一个人我们只需要存储其坐的位置编号,然后用链表实现将他们串起来即可,同时。此外,考虑到他们是围着圈报数的,故用循环链表实现。
2.如何实现报数以及自杀的过程呢?
自杀其实就是将此位置的人删除出链表中,然后接着报数就是让下一次计数的起始位置变成死掉人的下一个。
好了,有了上面的基础,我们就可以写出我们模拟实现的代码了。

#include"queue.h"

int main()
{
	int* left;
	int i;
	struct Queue* Q = CreateQueue();
	if (Q != NULL)
	{
		//把圈初始化为41人大小
		InitQueue(41, Q);
		//当人数不够了,就跳出循环
		while (KillMember(Q))
		{
			continue;
		}
		left = CheckLeft(Q);
		//只剩下KILLNUM-1个人了
		printf("剩下的人是在原本的第");
		for (i = 0; i < KILLNUM - 1; i++)
		{
			printf("%d", left[i]);
			if (i != KILLNUM-2)
			{
				printf(",");
			}
		}
		printf("位\n");
		free(left);
		left = NULL;
	}
}
/*
	这是queue.h
*/
#include<stdio.h>
#include<stdlib.h>
//报到KILLNUM就杀一个人,且该数字不为1
#define KILLNUM 3
struct people;
typedef struct people* PtrToPeo;

//创建一个圈
struct Queue* CreateQueue();
//对圈进行初始化,把n个人放进去,并给每个人编号
void InitQueue(int n,struct Queue* Q);
//模拟每次计数后人自杀的情况
int KillMember(struct Queue* Q);
//查看Q中剩余的人原先的位置在哪里
int* CheckLeft(struct Queue* Q);

//模拟围成的圈,并记录剩余人数(不要在意名字我不太会取)
struct Queue{
	int sz;
	PtrToPeo queue;
};

struct people{
	int position;
	PtrToPeo next;
};
/*
	这是queue.c
*/

#include"queue.h"

//将圈设置为n个人,然后依次对进行编号
void InitQueue(int n,struct Queue* Q)
{
	Q->sz = n;
	int count = 1; 
	PtrToPeo first=malloc(sizeof(struct people));
	PtrToPeo pnow, pnext;
	if (first == NULL)
		exit(EXIT_FAILURE);
	else
	{
		Q->queue = first;
		pnow = first;
		pnow->position = count;
	}
	//对Q这个圈进行初始化成有n个人,把每个人的编号给填进去
	while (count<n)
	{
		pnext = malloc(sizeof(struct people));
		if (pnext != NULL)
		{
			pnow->next = pnext;
			pnow = pnext;
			pnow->position=(++count);
		}
	}
	pnow->next = first;
}

//成功杀人返回1,否则返回0
int KillMember(struct Queue* Q)
{
	//如果人不够,就杀不了人
	if (Q->sz < KILLNUM)
		return 0;
	else
	{
		PtrToPeo prev = Q->queue;
		PtrToPeo pnow=prev->next;
		int i = 2;
		while (i != KILLNUM)
		{
			prev = pnow;
			pnow = pnow->next;
			i++;
		}
		prev->next = pnow->next;
		//杀完人之后要把队首变成自杀者的后面一个,用作下一次报数的起点
		Q->queue = pnow->next;
		free(pnow);
		Q->sz--;
		return 1;
	}
}

//返回值不用了就free掉
int* CheckLeft(struct Queue* Q)
{
	int i;
	PtrToPeo pnow = Q->queue;
	int* ret = malloc(sizeof(int)*Q->sz);
	for (i = 0; i < Q->sz; i++,pnow=pnow->next)
	{
		ret[i] = pnow->position;
	}
	return ret;
}

struct Queue* CreateQueue()
{
	return malloc(sizeof(struct Queue));
}

程序运行结果如下:
在这里插入图片描述
当然,我们也可以修改KILLNUM和n的值,从而计算不同情形下的安全位置,说不定关键时候会有帮助哦~~

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值