您的位置:首页 > 其它

借助链表解决猴子选大王问题(约瑟夫环问题)

2016-03-30 18:55 441 查看
Q:一群猴子,编号是1,2,3 …m,这群猴子(m个)按照1~m的顺序围坐一圈。从第1只开始数,每数到第n个,该猴子就要离开此圈,这样依次下来,直到圈中只剩下最后一只猴子,则该猴子为大王。输入m和n,输出为大王的猴子是几号。

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);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: