【数据结构】实践作业:加里森的任务

零、效果展示

一、题目要求

        有n个加里森敢死队的队员要炸掉敌人的一个军火库,谁都不想去,队长加里森决定用轮回数数的办法来决定哪个战士去执行任务。规则如下:如果前一个战士没完成任务,则要再派一个战士上去。现给每个战士编一个号,大家围坐成一圈,随便从某一个编号为x的战士开始计数,当数到y时,对应的战士就去执行任务,且此战士不再参加下一轮计数。如果此战士没完成任务,再从下一个战士开始数数,被数到第y时,此战士接着去执行任务。以此类推,直到任务完成为止。
        加里森本人是不愿意去的,假设加里森为1号,请你设计一程序为加里森支招,求出n,x,y满足何种条件时,加里森能留到最后而不用去执行任务。

要求:
(1)主要数据结构采用链式结构存储。
(2)自拟实验实例验证程序正确性,并讨论n,x,y之间的关系。

二、需求分析

任务描述

设计一个程序解决加里森的任务问题。该问题要求根据给定的条件(n、x、y),找出使加里森不用去执行任务的组合。具体规则如下:

  • 有 n 个加里森敢死队的队员要炸掉敌人的一个军火库。
  • 每个队员都有一个编号,编号从 1 到 n。
  • 以编号为 x 的战士为起始点,从1开始循环数数,每数到第 y 个战士,该战士将去执行任务。
  • 如果某个战士执行任务失败,则会重新开始数数,直到任务完成为止。
  • 加里森本人是不愿意去执行任务的,他的编号永远为1。

输入要求

  • 输入形式:通过命令行或交互界面输入 n、x、y 的值。
  • 输入值的范围:n、x、y 均为正整数,且满足 1 <= x <= n,1 <= y <= 2*n(自定义)。

输出要求

  • 输出形式:输出符合条件的 x 和 y 的组合。
  • 输出内容:程序将输出满足条件的 x 和 y 值,使得加里森不用去执行任务。

功能描述

  • 程序能够根据输入的 n、x、y 值,计算出使加里森不用去执行任务的组合。
  • 程序能够处理正确的输入,并输出符合条件的 x 和 y 值。
  • 程序能够处理错误的输入,并给出相应的错误提示或处理方式。

测试数据

  • 正确的输入数据:例如 n=5,y=2,期望输出为 x=6。
  • 错误的输入数据:例如 n=0,期望输出为错误提示或处理方式。

二、 概要设计

思路概述

  • 使用链表结构模拟加里森的任务问题,每个节点代表一个队员,节点之间通过指针连接成环形链表。
  • 设计函数来初始化链表、删除节点、打印链表等操作,根据规则模拟任务执行过程,找出符合条件的 x 和 y 的组合。

数据结构定义

  • 定义链表节点结构体 LinkNode,包含数据 data 和指向下一个节点的指针 next

主程序流程

  1. 提供交互式界面,让用户输入 n、x、y 的值。
  2. 根据用户输入的值调用相应的函数进行计算和处理。
  3. 输出符合条件的 x 和 y 的组合,或者输出错误提示信息。

程序模块层次关系

  • 主程序模块:负责处理用户输入、调用相应函数、输出结果。
  • 初始化链表模块:负责创建空链表和添加节点。
  • 模拟模块:根据规则进行模拟运行并删除节点。
  • 输出结果模块:根据计算结果输出符合条件的 x 和 y 的组合,或者输出错误提示信息。

三、详细设计

主体思路

主函数 main
  |
  |--> function//面向用户的交互模块
         |
         |--> Garrison_x//基于(n,y)求解(x)
         |      |--> x++
         |            |--> CreateHeadNode + InitList//初始化n人链表
         |                    |--> DeleteNode
         |                    |--> PrintList
         |
         |--> Garrison_x_y//基于(n)求解(x,y)
         |      |-->  x++
         |             |-->  y++
         |                    |--> CreateHeadNode + InitList//初始化n人链表
         |                            |--> DeleteNode
         |                            |--> PrintList

 结构体定义

//定义节点结构体
typedef struct linknode {
	int data;
	struct linknode* next;
}LinkNode;

函数定义

LinkNode* CreateHeadNode(void);//创建头结点
void CreateNewNode(LinkNode* H,int data);//创建元素节点
void PrintList(LinkNode* H);//打印链表
void DeleteNode(LinkNode* H, int num);//删除节点
void InitList(LinkNode* H,int num);//初始化链表

void Garrison_x(int n, int y, int isPrt);//固定n,y求x
void Garrison_x_y(int n, int isPrt);//固定n求x,y

void function();//面向用户的交互模块

执行函数

void Garrison_x(int n, int y, int isPrt)//固定n,y求x
{
	for (int x = 1; x <= n; x++)
	{
		//根据n值初始化链表
		LinkNode* H = CreateHeadNode();
		pre = H;
		InitList(H, n);

		if (isPrt) PrintList(H);//打印初始化后的链表

		for (int j = 0; j < x-1; j++)//将pre指向上次执行者的前一个人
			pre = pre->next;

		while (H->data > 1)//当前链表剩余元素个数>1?继续进行删除操作:退出
		{
			DeleteNode(H, y);
			if (isPrt) PrintList(H);
		}
		if (H->next->data == 1)//如果1号(加里森)活了下来
			printf("\n*** x = %d ***\n\n", x);
		else//似了
			if (isPrt) printf("x = %d is wrong\n", x);
	}
}

void Garrison_x_y(int n, int isPrt)//固定n求x,y
{
	for (int x = 1; x <= n; x++)
	{
		for (int y = 1; y <= 2 * n; y++)//设置y的上限是2n,可根据需求进行修改
		{
			LinkNode* H = CreateHeadNode();
			pre = H;
			InitList(H, n);
			if(isPrt) PrintList(H);		
			for (int j = 0; j < x-1; j++)
				pre = pre->next;
			while (H->data > 1)
			{
				DeleteNode(H, y);
				if (isPrt) PrintList(H);
			}
			if (H->next->data == 1)
				printf("\n*** x = %d  y = %d***\n\n", x,y);
			else
				if (isPrt) printf("x = %d  y = %d is wrong\n", x,y);
		}
	}
	
}

交互模块

void function()
{
	int func = 0;
	int isPrt = 0;
	int n, x, y;
	printf("\n请输入想要执行的功能('1'表示(n,y)->(x),'2'表示(n)->(x,y),'0'表示退出程序):" );
	scanf_s("%d", &func);
	switch (func) {
		case 0:
			exit(0);
		case 1:
			printf("\n请输入n=");
			scanf_s("%d", &n);
			printf("\n请输入y=");
			scanf_s("%d", &y);
			if (n <= 0 || y <= 0)
			{
				printf("输入不合法,请重新输入");
				break;
			}
			printf("\n请选择打印模式('1'表示'全过程','0'表示'精简'):");
			scanf_s("%d", &isPrt);
			Garrison_x(n, y, isPrt);
			break;
		case 2:
			printf("\n请输入n=");
			scanf_s("%d", &n);
			if (n <= 0)
			{
				printf("输入不合法,请重新输入");
				break;
			}
			printf("\n请选择打印模式('1'表示'全过程','0'表示'精简'):");
			scanf_s("%d", &isPrt);
			Garrison_x_y(n, isPrt);
			break;
		default:
			printf("\n输入错误!请检查输入");
			break;
	}
		
}

四、 调试分析报告

时间复杂度

        对于(n,y)->x,当固定n与y时,对于每一个x,删除节点操作执行n-1次,每次删除会移动工作指针y次,时间复杂度为O(n^2*y)。

        对于(n)->(x,y),当固定n,再固定x时,对于每一个y,删除节点操作执行n-1次,每次删除会移动工作指针y次,时间复杂度为O(n^4)。

空间复杂度

        链表操作的空间复杂度为O(n)

发现

        当(n)->(x,y)时,xy的对数与y的取值范围相同。换句话说,当n一定时,对于任意的y,都能找到唯一确定的x与之对应。

五、用户使用说明

  • 运行程序后,程序将会显示如下提示信息:
请输入想要执行的功能('1'表示(n,y)->(x),'2'表示(n)->(x,y),'0'表示退出程序):
  • 根据提示输入想要执行的功能对应的数字,例如输入 1表示执行 (n,y)->x 的功能。

  • 根据程序提示依次输入相关参数:

    • 对于功能 1,需要依次输入 n 和 y 的值,确保输入的值大于 0。
    • 对于功能 2,需要输入 n 的值,确保输入的值大于 0。
  • 如果输入的值不合法(小于等于 0),程序将会提示重新输入。

  • 程序会根据输入的参数执行相应的功能,并输出结果或过程。

  • 如果需要继续测试或执行其他功能,可以重复上述操作进行。

  • 如果需要退出程序,可以输入 0 并按回车键退出。

六、 测试结果

mode:(n,y)->(x) simply 
input:n=-1,y=3
output:

    输入不合法,请重新输入
mode:(n,y)->(x) simply 
input:n=10,y=3
output:

    *** x = 7 ***
mode:(n,y)->(x) all
input:n=3,y=1
output:

    List:   1       2       3
    List:   1       3
    List:   1

    *** x = 1 ***

    List:   1       2       3
    List:   1       2
    List:   2
    x = 2 is wrong
    List:   1       2       3
    List:   2       3
    List:   3
    x = 3 is wrong
mode:(n)->(x,y) simply
input:n=6
output:

    *** x = 1  y = 3***

    *** x = 1  y = 5***

    *** x = 2  y = 1***

    *** x = 3  y = 2***

    *** x = 3  y = 4***

    *** x = 3  y = 7***

    *** x = 3  y = 9***

    *** x = 4  y = 6***

    *** x = 4  y = 11***

    *** x = 5  y = 8***

    *** x = 5  y = 12***

    *** x = 6  y = 10***

  • 35
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Matr1x_Yu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值