约瑟夫游戏的大意:30 个游客同乘一条船,因为严重超载,加上风浪大作,危险万分。因此船长告诉乘客,只有将全船一半的旅客投入海中,其余人才能幸免于难。无奈,大家只得同意这种办法,并议定30 个人围成一圈,由第一个人数起,依次报数,数到第9 人,便把他投入大海中,然后再从他的下一个人数起,数到第9 人,再将他投入大海中,如此循环地进行,直到剩下15 个游客为止。问:哪些位置是将被扔下大海的位置?
(1)不失一般性,将30 改为一个任意输入的正整数n,而报数上限(原为9)也为一个任选的正整数k。
(2)要求使用顺序存储结构和链式存储结构分别实现。
(1)不失一般性,将30 改为一个任意输入的正整数n,而报数上限(原为9)也为一个任选的正整数k。
(2)要求使用顺序存储结构和链式存储结构分别实现。
输入:三个数:n,k,n1,分别表示开始时的总人数,要出队的序号数和最终要剩下的人数。
输出:按顺序输出出队人的序号,以及还剩下的人的序号。
数组实现代码如下:
#include <stdio.h>
int book[1005]={0}; //数组用来记录当前状态
int main() {
int n,k,n1,num=0,flag=0,i=0;
scanf("%d%d%d",&n,&k,&n1); //n:总人数;k:出队的序号;n1:最终要剩下多少人
printf("死:\n");
while(num!=n-n1) { // num:已经出队的人数
if(!book[i]) { //如果book为0,表示未出队
flag++; //当前序号增1
if(flag==k) { //当前序号与要出队的序号比较
printf("%d ",i+1);
num++; //已经出队的人数加一
flag=0; //当前序号设为0
book[i]=1; //状态位改为1
}
}
i=(i+1)%n; //每次判断是否出队后i增1(循环)
}
printf("\n生:\n");
for(i=0;i<n;i++)
if(!book[i])
printf("%d ",i+1);
printf("\n");
return 0;
}
链表实现代码如下:
#include <stdio.h>
#include <stdlib.h>
typedef struct node { //结点数据域表示序号
int data;
struct node *next;
}Node;
int main() {
int n,k,n1,i; //n:总人数;k:要出队的序号;n1:最后要留下的人数
scanf("%d%d%d",&n,&k,&n1);
Node *head=(Node *)malloc(sizeof(Node)); //头结点
head->next=NULL;
for(i=0;i<n;i++) { //建立链表,前插
Node *p=(Node *)malloc(sizeof(Node));
p->data=n-i;
p->next=head->next;
head->next=p;
}
Node *q;
q=head;
while(q->next) { //寻找最后一个节点
q=q->next;
}
q->next=head->next; //最后一个结点的指针指向第一个结点,建立循环链表
Node *r;
int num=0,flag=0; //num记录已经出队的人数,flag记录当前结点对应的数字
printf("死:\n");
while(num<n-n1) { //剩下的人多于n1
r=q; //q为最后一个结点
flag=(flag+1)%k; //flag加一(循环)
r=r->next; //r为第一个结点
if(!flag) { //flag为0,出队
num++;
q->next=r->next;
if(r==head->next) { //如果删除的是第一个结点,头指针指向下一个
head->next=r->next;
}
printf("%d ",r->data);
free(r); //删除该结点
}
else { //flag不为0,继续寻找下一个
q=q->next;
}
}
q=head;
printf("\n生:\n");
for(i=0;i<n1;i++) {
printf("%d ",q->next->data);
q=q->next;
}
printf("\n");
return 0;
}