2021-03-11

题目1:猴子选王(学时:6)
一堆猴子有m个,编号分别是1,2,3 …m,这m个猴子按照编号1,2,…,m的顺序围坐一圈,然后从第1开始数,每数到第n个,该猴子就要离开此圈,这样依次下来,直到圈中只剩下最后一只猴子,则该猴子就为大王。
要求:分别采用向量及链表两种存储方式实现该问题的求解,给出一组m和n,输出对应的猴王。

实验思路:
数组法是使用类似于循环的方法,在每一次达到数组的最后一个时,就重置为0,重新开始遍历,使用数组先初始化猴子的位次,然后利用取余的方法进行往后数,在循环结束之后存储最终结果。
链表法是使用相应链表进行存储结点,在数到相应位置时进行删除操作,即为猴子离圈操作,在主函数中调用约瑟夫规则的函数,在循环相应次数后,得出相应结果,最后存储在文件当中。

  1. 数组法:
#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;
}
  1. 链表法:
 #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;
  }

实验结果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值