今天介绍约瑟夫出圈问题,关于问题的介绍如下:
为了证明约瑟夫的选择是正确的,我们可以想办法用代码来模拟这个过程。
下面是模拟过程:
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的值,从而计算不同情形下的安全位置,说不定关键时候会有帮助哦~~