题目
一堆猴子都有编号,编号是1,2,3 …m,这群猴子(m个)按照1-m的顺序围坐一圈,从第1开始数,每数到第n个,该猴子就要离开此圈,这样依次下来,直到圈中只剩下最后一只猴子,则该猴子为大王。
一、解题思路
1.向量解法(数组解法):
第一步 首先将所有猴子进行初步编号(从1到n)4
第二步 因为所有猴子只有两种状态:淘汰与未被淘汰。所以将所有猴子进行状态编
号(0表示未淘汰,1表示被淘汰),先将所有猴子标记为0,表示未淘汰。
第三步:在主函数里开始循环报数淘汰猴子,用另一个计数变量K来统计报数猴子,当k和要淘汰的猴子报的数字相等时,淘汰该猴子,k值清零再次循环,知道猴子剩余数量j等于1时结束循环
第四步:遍历数组,找到状态参数为0的猴子就是猴子王
2.链表解法:
第一步:构建循环环状链表,存放猴子编号
第二步:报数找到淘汰数字前一个猴子,对应就能找到要被淘汰的猴子
第三步:删除淘汰猴子的结点,释放空间
第四步:让被淘汰猴子的下一个结点开始报数,循环此过程
第五步:知道猴子剩余数量为1时候,结束循环,函数返回剩下那个猴子的编号信息。即猴王编号
二、方法优缺点
1.向量法
1)优点:
1.数组能够支持下标访问,访问效率很高;
2.查找速度很快;
2)缺点:
1.数组的大小要提前声明,容易造成大额空间浪费,也容易出现空间不足需要重新定义数组的情况;
2.元素的插入删除也不方便操作,只能使用状态变量来标记猴子;
2.链表法:
1)优点:
1.插入,删除操作很便捷,在结点上操作十分灵活。
2.大小不固定,容易扩展;
3.内存的利用效率也很高,不会浪费内存;
2)缺点:
1.每次遍历数据时只能从头开始,查找效率很低。
2.随机访问效率低
三、流程图
1.向量法(数组法)
2.链表法
四、实验代码
#include <stdio.h>
#include <stdlib.h>
#define N 100 //宏定义向量长度
int main()
{
int a[N],n,m;
printf("请输入猴子的个数:\n");
scanf("%d",&m);
printf("请输入要淘汰的数字:\n");
scanf("%d",&n);
int i,j,k;
k=0;
j=m;// 计数变量,用来统计剩余猴子数量
for(i=0; i<m; i++)
a[i]=0;//对这些猴子进行状态编号,分为0,1,(0状态为正常猴子,1状态是被淘汰猴子)
if(n==1||m==1)
printf("此情况无意义");
else for(i=0;j!=1;)
{
if(a[i]==0)
{
k++;//用来再一次重头统计猴子数目
}
if(k==n)//如果重头编号时候K和要淘汰的数字相等时,该猴子淘汰。k重新计数
{
a[i]=1;//该猴子状态改变,变为淘汰态:1
k=0;//k清零重新计数
j--;//剩余猴子数减一
}
i++;
if(i==m)//此时最后一个猴子报完数,一圈已经结束。i清零后开始下一圈剩余猴子报数
{
i=0;
}
}
for(i=0; i<m; i++)
{
if(a[i]==0)//此时还是0状态的猴子就是王
printf("猴子王是最初的%d号猴子\n",i+1);
}
return 0;
}
2. 链表法代码
#include <stdio.h>
#include <stdlib.h>
typedef struct monkey
{
int data;
struct monkey *next;
} Monkey;
int create(int m, int n)//m猴子数量,n是要淘汰的数字
{
Monkey *head,*q,*p,*t;
head = (Monkey*)malloc(sizeof(Monkey));
p=head;
p->data = 1;//存放第一个猴子数据
p->next = p;//构建循环链表
for(int i=2 ; i<=m ; i++)
{
t=(Monkey*)malloc(sizeof(Monkey));
t->data=i;
t->next=p->next;
p->next=t;
p=p->next;//这个循环不断申请空间,将存放信息的结点插入链表
}
p=head;//形成闭环,循环链表
q=head;//在后面用来寻找淘汰猴子的前驱
int j=n;//j用来统计剩余猴子数目
while(j!=1)//当j等于1,即剩余一个猴子时候结束循环
{
for(int i=1; i<n; i++) //报数过程,报到n-1时停止,下一个就是要被淘汰的猴子
{
p = p->next;
}
while (q->next != p)//让q指向要淘汰猴子的前驱
{
q = q->next;
}
q->next=p->next;//删除这个淘汰猴子的结点
p = p->next;//让p从被淘汰猴子的后一位再开始新的报数
j--;//淘汰一个猴子,总猴子数目减一
}
int king = p->data;//返回剩余那个猴子的编号
free(p);
return king;
}
int main()
{
int t,m,n;
printf("请输入猴子的个数:\n");
scanf("%d",&m);
printf("请输入要淘汰的数字:\n");
scanf("%d",&n);
t=create(m,n);
printf("最后的猴王是最初的第%d个猴子",t);
return 0;
}