借助链表解决猴子选大王问题(约瑟夫环问题)
2016-03-30 18:55
441 查看
Q:一群猴子,编号是1,2,3 …m,这群猴子(m个)按照1~m的顺序围坐一圈。从第1只开始数,每数到第n个,该猴子就要离开此圈,这样依次下来,直到圈中只剩下最后一只猴子,则该猴子为大王。输入m和n,输出为大王的猴子是几号。
A:用一个循环单链表来表示这一群猴子。节点含有0:一个保存猴子的编号,一个为指向下一只猴子的指针,编号为m的结点再指向编号为1的结点,以此构成环形的链。当数到第n个时,该结点被删除,继续数,直到只有一个结点。(这个问题是经典的算法问题,很多问题可以抽象成这个问题)
代码如下:
Q2:(约瑟夫问题)
此问题与猴子选大王类似,只不过是从选猴王变成了自杀,不再赘述,代码如下:
A:用一个循环单链表来表示这一群猴子。节点含有0:一个保存猴子的编号,一个为指向下一只猴子的指针,编号为m的结点再指向编号为1的结点,以此构成环形的链。当数到第n个时,该结点被删除,继续数,直到只有一个结点。(这个问题是经典的算法问题,很多问题可以抽象成这个问题)
代码如下:
#include<stdio.h> #include<time.h> #include<stdlib.h> #define OK 1 #define ERROR 0 #define TRUE 1 #define FALSE 0 #define maxsize 10 typedef int status; typedef int elemtype; typedef struct node{ elemtype num; struct node * next; }node; typedef struct node* linklist; int main(void){ linklist p,q,head; int m,n,king,i,j; scanf("%d %d",&m,&n); if(m==1)//只有一只猴子时猴王为1 king=1; p=q=(linklist)malloc(sizeof(node));//给新节点分配空间 head=p;//head指向首元素节点 head->num=1;//给第一只猴子编号 for(i=1;i<m;i++){//建立m只猴子围成的圆圈 p=(linklist)malloc(sizeof(node));//p为等待插入的节点 p->num=i+1;//p的编号为i+1 q->next=p;//q始终记录尾节点(实质是链表的尾插法) q=p; } q->next=head;//链表尾指向链表头 p=head;//开始计数 for(i=1;i<m;i++){//循环m-1轮,淘汰m-1只猴子 for(j=1;j<n-1;j++){//让p指向要淘汰的元素的前驱元素 p=p->next; } q=p->next;//q指向要淘汰的猴子 printf("第%d轮淘汰第%d只猴子\n",i,q->num); p->next=q->next;//删除q p=q->next;//一定要让下一次计数起点为被删除元素的后继 free(q);//释放q } king=p->num; free(p); printf("猴王是第%d\n",king); }
Q2:(约瑟夫问题)
此问题与猴子选大王类似,只不过是从选猴王变成了自杀,不再赘述,代码如下:
/*约瑟夫环*/ #include<stdio.h> #include<stdlib.h> #define OK 1 #define ERROR 0 typedef int status; typedef int elemtype; typedef struct people{ elemtype num; struct people * next; }people; typedef struct people* linklist; int main(void){ linklist pmove,qmove,head; int people,num,killed,start,i,j; printf("请输入总人数,开始报数的人的位置和报数间隔:(用空格隔开)\n"); scanf("%d %d %d",&people,&start,&num); if(people==1){ printf("无幸存者\n"); return OK; } else{ pmove=qmove=(linklist)malloc(sizeof(people)); head=pmove; pmove->num=1; for(i=1;i<people;i++){ pmove=(linklist)malloc(sizeof(people)); pmove->num=i+1; qmove->next=pmove; qmove=pmove; } qmove->next=head; i=0; pmove=head; while(i<start-1){ pmove=pmove->next; i++; } for(i=1;i<people;i++){ for(j=1;j<num-1;j++){ pmove=pmove->next; } qmove=pmove->next; printf("第%d轮杀死编号为%d的人\n",i,qmove->num); pmove->next=qmove->next; pmove=qmove->next;/*一定要让下一轮循环的起点为被删除元素的后继*/ free(qmove); } } killed=pmove->num; free(pmove); printf("幸存者为%d号\n",killed); }
相关文章推荐
- 装饰模式笔试
- 项目4-长方柱类
- 常见linux笔试题-100道选择题-(答案见最后)
- Java泄露及造成内存泄露的原因
- IOS学习之——静态单元格
- Cstring到string
- Java 模板引擎总结
- android日期格式化
- URL.createObjectURL和URL.revokeObjectURL
- IOS学习之——通知中心NSNotificationCenter
- jsp页面用el表达式获取枚举的code
- 文档在线预览的实现
- static关键字
- jquerymobile使用技巧
- 2016-03-30 AOP
- MySQL主从复制(Master-Slave)与读写分离(MySQL-Proxy)实践
- 【小项目 日程表程序】最近frank我想到一个好项目(好吧,我同意不是我想的)
- 第二篇——坚持!!
- IOS学习之——延迟执行
- SVN命令