约瑟夫问题

/*
说明据说着名犹太历史学家Josephus有过以下的故事:在罗马人占领乔塔帕特后,39 个犹
太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人到,于是决定了
一个自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀,
然后再由下一个重新报数,直到所有人都自杀身亡为止。
*/

 


由上可知,最后一个自杀的是在第31个位置,而倒数第二个自杀的要排在第16个位置,之前的
人都死光了,所以他们也就不知道约琴夫与他的朋友并没有遵守游戏规则了。

代码实现:

 1 #include<stdio.h>
 2 #include<stdlib.h>
 3 #define NUM 41    //游戏人数
 4 #define OUT 3    //出局序号
 5 
 6 typedef struct Person    //表示一个人的结构体
 7 {
 8     int num;
 9     Person * next;
10 }Person;
11 
12 int main()
13 {
14     int i,cnt;
15     /*
16     **先创建NUM个人,且将他们围成一圈(一个循环链表)
17     */
18     Person  *q,*p,*s,*r,* head = (Person*)malloc(sizeof(Person));    //
19     r=head;                                                            //
20     head->num = 1;                                                    //    创建第一个结点
21     for(i=2; i<=NUM ; i++)                                            //尾插法建链表
22     {
23         s = (Person*)malloc(sizeof(Person));
24         s->num = i;
25         r->next = s;
26         r = s;
27     }
28     r->next = head;                                                    //闭环
29     /*
30     **开始游戏
31     */
32     printf("游戏人数是 %d 人,逢 %d 出局\n",NUM,OUT);
33     printf("出局顺序为:\n");
34     cnt = 1;
35     p = head;
36     while(p->num != p->next->num)        //是否剩下最后一个结点
37     {
38         cnt++;                            //先看下一个数是什么
39         if(cnt == OUT)                    //如果是出局的数,那么做以下处理
40         {
41             q = p->next;                //先暂存下一个结点地址
42             printf("%d ",q->num);        //打印即将出局的结点序号
43             p->next = p->next->next;    //从循环链表中将该点去掉q指向的点去掉
44             p = p->next;                //将p往后移一位
45             free(q);                    //释放删除的结点的内存
46             q = NULL;                    //将q置空
47             cnt = 1;                    //从p所指向的当前位置开始数
48         }else
49             p=p->next;                    //如果不满足出局的数,那就往后数。
50     }    
51     putchar(10);                        //换行
52     printf("最后剩余 %d \n ",p->num);    //打印最后一个数
53     free(p);                            //释放最后一个结点的内存
54     return 0;
55 }

 

转载于:https://www.cnblogs.com/houjun/p/6507686.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值