题目1:猴子选王(学时:6)
一堆猴子有m个,编号分别是1,2,3 …m,这m个猴子按照编号1,2,…,m的顺序围坐一圈,然后从第1开始数,每数到第n个,该猴子就要离开此圈,这样依次下来,直到圈中只剩下最后一只猴子,则该猴子就为大王。
要求:分别采用向量及链表两种存储方式实现该问题的求解,给出一组m和n,输出对应的猴王。
实验思路:
数组法是使用类似于循环的方法,在每一次达到数组的最后一个时,就重置为0,重新开始遍历,使用数组先初始化猴子的位次,然后利用取余的方法进行往后数,在循环结束之后存储最终结果。
链表法是使用相应链表进行存储结点,在数到相应位置时进行删除操作,即为猴子离圈操作,在主函数中调用约瑟夫规则的函数,在循环相应次数后,得出相应结果,最后存储在文件当中。
- 数组法:
#include <stdio.h>
#include<stdlib.h>
#define N 100
int main()
{
int m,n;
FILE *fp;//文件指针
/*文件的打开*/
fp=fopen("data.txt","w");//fopen打开文件。“w”以写入的形式打开,“r”以读的形式打开
if(fp==NULL) //判断如果文件指针为空
{
printf("File cannot open! " );
exit(0);//在以0的形式退出,必须在文件开头有#include <stdlib.h>,stdlib 头文件即standard library标准库头文件
}
printf("请输入m和n的值:\n");
scanf("%d%d",&m,&n);
int a[N] = {0};//数组初始化
int i,j;
for(i = 0; i < m; i++)//将数组的每个元素初始化为猴子的位次
{
a[i] = i+1;
}
i=0;
while (m > 1)
{
i = (i+n-1) % m;//淘汰的猴子,利用取余的方法模拟循环
for(j = i+1; j < m; j++)
{
a[j-1] = a[j];//将后面的一个向前移一位
}
m--;
if(i == m)//遇到终点时,开始起点
{
i = 0;
}
}
fprintf(fp,"%d\n", a[i]);//保存数据
printf("对应的猴王是%d\n",a[i]);//打印结果
fclose(fp);
return 0;
}
- 链表法:
#include <stdio.h>
#include<stdlib.h>
#include <malloc.h>
#define len sizeof(Node)
FILE *fp;
typedef struct node{ //循环链表结构
int number;
struct node *next;
}*Link,Node;
Link creat(int m)//创建n个结点的链表
{
int i;
Link head=NULL,tail=NULL;
for(i=1;i<=m;i++){
if(i==1)
head=tail=(Link)malloc(len);
else{
tail->next=(Link)malloc(len);
tail=tail->next;
}
tail->number=i;
tail->next=NULL;
}
tail->next=head; //全部建立完成后将首尾相连形成环
return head; //返回建好的头结点
}
Link delete(Link s) //删除循环链表中的结点s
{
Link p=s;
while(p->next!=s)
p=p->next;
p->next=s->next;
free(s);
return p->next;//返回结点的下一个结点的指针
}
void Josephu(Link p,int m,int n)//按约瑟夫规则依次输出结点
{
int i,j;
for(i=1;i<m;i++){ //分别循环(m-1)次和(n-1)次
for(j=1;j<n;j++)
{p=p->next;}
p=delete(p); //从表中删除
}
printf("对应的猴王是%d\n",p->number);//将最后剩的输出
fprintf(fp,"%d\n",p->number);
}
int main(void)
{
/*文件的打开*/
fp=fopen("data.txt","w");//fopen打开文件。“w”以写入的形式打开,“r”以读的形式打开
if(fp==NULL) //判断如果文件指针为空
{
printf("File cannot open! " );
exit(0);//在以0的形式退出,必须在文件开头有#include <stdlib.h>,stdlib 头文件即standard library标准库头文件
}
int m,n;
Link head=NULL;
printf("请输入m和n的值:\n");
scanf("%d%d",&m,&n);
head=creat(m);
Josephu(head,m,n);
fclose(fp);
return 0;
}
实验结果: