数据结构实验报告-排序、查找及其应用

数据结构实验报告-排序、查找及其应用

一、问题分析

(1)题目一中,要求在坐标系中设立邮局,使得各个居民到邮局路程的和最小。题目中比较关键的信息时居民走到邮局是走平行于坐标轴的路径,不是直线路径。因为路径与坐标轴平行,所以x轴和y轴是可以独立分析的。这样,只要居民的位置确定了,它的横坐标与纵坐标的对应关系并不用关心,只要分别求出在两个坐标轴上各点到邮局在该坐标轴上投影的点的最小距离,两个局部最小之和即是全局最小。因为要求出各点到投影点的最小距离,一个按升序排列的点坐标可以在只遍历一次所有居民位置的情况下,按照递推公式以O(n)的时间复杂度得到最小距离。所以还要对居民的横坐标和纵坐标分别进行排序。因为数据的无序性,采用平均时间复杂度的O(nlog2n)的快速排序即可。
(2)题目二中,邮递员的年龄范围很小,限定在18到65岁,并且要求时间和空间复杂度都为O(n)。对于这种比较小的数据范围,采用桶排序是很适合的。每个年龄对应一个桶,因为题目不需要知道每个年龄有多少人,只要在那个年龄有邮递员,就将这个桶标记为1即可。读入所有数据后,从18遍历到65,只要有值,就拿它与上一个有值的年龄相减,维护一个最大值就可以得到答案。
(3)题目三中,邮递员和街道的关系是多对一,但是一个邮递员只负责一个街道。现在需要根据部分邮递员的回答来计算最小可能的邮递员总数。分析可以知道,不同回答的邮递员一定不会负责同一条街道,相同回答的邮递员可以假设他们负责同一条街道。这样,可以把相同回答的邮递员尽可能分到相同条街道,当分配不够时,就得从没有回答问题的邮递员中加人来负责该街道。根据这个策略,可以先排序,这样相同回答的邮递员位置就会相邻,只需以O(n)时间复杂度遍历一遍回答的数组,就可以得到最后的答案。
三个题目都是依赖排序后数据排序连续的良好性质,在这个基础上进行相应的逻辑操作,减小后面操作的时间和空间复杂度。

二、详细设计

2.1设计思想

(1)题目一需要使用到排序算法。这里采用比较快的快速排序,分别对每个居民的横坐标和纵坐标进行排序,可以得到在x轴和y轴上从小到大的n个点。然后分别遍历两个坐标轴。以遍历x轴为例,先计算其上所有点到其上数值最小(最左边)的点的距离,然后就可以带入递推公式来计算其他点的距离。对于一点(a,0),所有点到(a-1,0)的距离d已经求出,则所有点到(a,0)的距离等于d加上a左边所有点的数量,再减去a-1右边所有点的数量。因为从(a-1,0)转移到(a,0),(a,0)左边每个点到(a,0)的距离相比于(a-1,0)时要增一,而对于(a-1,0)右边的点要减一,这两个因素共同作用的效果可以得到上述递推公式。两个坐标轴都维护一个最小值,他们对应坐标的交叉点就是邮局的最优地点。因为题目只要求求出最小值即可,最优坐标的信息可以不保留。最后将两个最小值相加就是所求答案。
(2)题目二采用桶排序。先设置一个大小为100的桶,实际上只用到18-65这个区间的桶即可。每读入一个年龄,就将该年龄对应的桶值置为1,表示该年龄有邮递员。读入完后,遍历桶中18到65的值,并用一个变量来保留上一个有值的桶下标(即相邻的年龄),如果有值就拿他的年龄与相邻年龄相减,维护这个差值的最大值就可以了。
(3)题目三先将所有回答进行快速排序,使相同回答的邮递员紧挨在一起。然后先将邮递员的初始数量置为已经回答的邮递员数量,然后开始对相同回答的邮递员配对分组。用一个变量sameAns记录上一个邮递员回答的值,一个变量sameCount记录目前有多少个邮递员分配到同一个街道。如果sameCount值等于sameAns时,说明可以配成一组,将sameCount的值置为-1,这个值是根据我的实现方式决定的,其实就是一个初始值;而如果在sameAns即将发生改变时,如果sameCount没有达到sameAns,即在已回答的邮递员中凑不成一组,则剩下的人需要在未回答的邮递员中补齐。这样遍历一遍回答的数组就可以得到最小可能的邮递员数量了。

2.2 存储结构及操作

2.2.1存储结构
实验中的数据存储都使用了基于线性存储的数组。
题目一中使用了int类型的数组x和y,分别记录每个居民的位置坐标。
题目二中使用了int类型的数组bucket,作为桶排序中的桶记录年龄。
题目三种使用了int类型的数组array,记录每位邮递员的回答。
2.2.2 涉及的操作
整个实验中用到的关键函数,如表 1所示。
在这里插入图片描述

在这里插入图片描述

表 1(续表)

2.3 程序整体流程

(1)题目二中的流程图如图 1所示。
在这里插入图片描述

图 1
(2)快速排序的流程图如图 2所示。
在这里插入图片描述

图 2
(2)题目一的流程图如图 3所示。
在这里插入图片描述

图 3

(3)题目三的整体流程和具体算法,如图 4所示。
在这里插入图片描述

图 4

三、用户手册

程序分为题目一,题目二和题目三,均采用从文件中读取数据的方式读入,并含有多组数据的读入。在程序运行后无需其他操作就可得到结果。
(1)题目一中,将会读取文件名为“5_1_input.in”的文件中数据,此文件要放置在.c文件的同一目录下。每组数据第一行为住户数目n,第2行到第n+1行为每个住户的横坐标和纵坐标。
对于每一组输入,程序都会输出分隔符:
======Case ======
另起一行输出一个整数,代表建立每个居民到邮局距离之和的最小值。
(2)题目二中,将会读取文件名为“5_2_input.in”的文件中数据,此文件要放置在.c文件的同一目录下。每组数据第一行为邮递员总数n,第2行有n个数,代表每一个邮递员的年龄。
对于每一组输入,程序都会输出分隔符:
======Case ======
另起一行输出一个整数,代表相邻年龄间隔的最大值。
(3)题目三中,将会读取文件名为“5_3_input.in”的文件中数据,此文件要放置在.c文件的同一目录下。每组数据第一行为参与回答的邮递员数目n,第2行有n个数,代表一个回答,即有多少个邮递员和他负责同一条街道。
对于每一组输入,程序都会输出分隔符:
======Case ======
另起一行输出一个整数,代表邮局最少的邮递员数目。

四、结果

结果只给出程序输出截图,文件部分的输入数据已打包进压缩包。

(1)题目一输出截图如图 5所示。
在这里插入图片描述

图 5

(2)题目二输出截图如图 6所示。
在这里插入图片描述

图 6
在这里插入图片描述

(3)题目三的截图如图 7所示。

图 7

五、总结

本次实验主要考察排序算法及其应用,对查找的要求不高。题目一和题目三主要采取快速排序对给出的完全随机无序的数据进行排序,题目二中根据题目要求以O(n)的时间复杂度解决问题且数据范围小,采用桶排序进行排序。排序在题目中是作为一个解决问题的工具,实验的主要逻辑是基于已有序的数据来完成的。题目一中需要根据题目给出的曼哈顿距离,判断出在x轴和y轴上分析问题时独立的,互不干扰。题目二在桶排序后,相邻年龄的邮递员在桶数组中位置也是相邻的,维护一个间隔最大值即可。题目三则是尽可能让相同回答的邮递员凑成一组,实在凑不成才从未回答的邮递员中加人。如果没有排序的预处理,后面处理问题的复杂度就会高出很多。
实验中我学会了使用时间复杂度O(nlog2n)的快速排序,也掌握了比较基础的时间和空间复杂度为O(n)的桶排序。解决问题时并没有运用特定的算法,而且在分析问题后,根据最优的策略来模拟,维护出最大值或者最小值就可以了。所以具体问题要具体分析,不能随便套模板就可以了。
实验中也遇到了不少难点。比如题目一对我来说还是比较难的,在课上完成时并没有想到x轴和y轴可以独立分析这一良好性质,而是采用时间和空间复杂度均为O(n2)的实现方法。在课后仔细思考时才有了突破点。所以解决问题的方法很多,如果多方面思考,有时可以很大程度地降低时间和空间复杂度。相信通过这一学期数据结构的学习,对以后掌握更多算法,培养计算机思维有很大帮助。

  • 15
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
1.实验目的 掌握内排序,比较各种排序的优、缺点。 2 需求分析 2.1原理 2.1.1、直接排序 算法描述:经过i-1遍处理后,L[1..i-1]己排好序。第i遍处理仅将L[i]插入L[1..i-1]的适当位置,使得L[1..i]又是排好序的序列。要达到这个目的,我们可以用顺序比较的方法。首先比较L[i]和L[i-1],如果L[i-1]≤ L[i],则L[1..i]已排好序,第i遍处理就结束了;否则交换L[i]与L[i-1]的位置,继续比较L[i-1]和L[i-2],直到找到某一个位置j(1≤j≤i-1),使得L[j] ≤L[j+1]时为止。 2.1.2、冒泡排序 算法描述:核心思想是扫描数据清单,寻找出现乱序的两个相邻的项目。当找到这两个项目后,交换项目的位置然后继续扫描。重复上面的操作直到所有的项目都按顺序排好。 2.1.3、快速排序 算法描述:首先检查数据列表中的数据数,如果小于两个,则直接退出程序。如果有超过两个以上的数据,就选择一个分割点将数据分成两个部分,小于分割点的数据放在一组,其余的放在另一组,然后分别对两组数据排序。通常分割点的数据是随机选取的。这样无论你的数据是否已被排列过,你所分割成的两个字列表的大小是差不多的。而只要两个子列表的大小差不多。 2.1.4、选择排序 算法描述:首先找到数据清单中的最小的数据,然后将这个数据同第一个数据交换位置;接下来找第二小的数据,再将其同第二个数据交换位置,以此类推。 2.1.5、堆排序 (1) 基本思想:堆排序是一树形选择排序,在排序过程中,将R[1..N]看成是一颗完全二叉树的顺序存储结构,利用完全二叉树中双亲结点和孩子结点之间的内在关系来选择最小的元素。 (2) 堆的定义: N个元素的序列K1,K2,K3,...,Kn.称为堆,当且仅当该序列满足特性: Ki≤K2i Ki ≤K2i+1(1≤ I≤ [N/2]) 2.1.6、希尔排序 算法描述:在直接插入排序算法中,每次插入一个数,使有序序列只增加1个节点,并且对插入下一个数没有提供任何帮助。如果比较相隔较远距离(称为增量)的数,使得数移动时能跨过多个元素,则进行一次比较就可能消除多个元素交换。 2.2要求 1.本程序对以下六种常用内部排序算法进行实测比较:冒泡排序,插入排序,选择排序,希尔排序,快速排序,堆排序。 2.排序的元素的关键字为整数。用正序,逆序,不同乱序的数据作测试比较。比较的指标为有关键字参加的比较次数和关键字的移动次数。 3.程序以人机对话的形式进行,每次测试完毕显示各种比较指标值 。 2.3任务 设计一个测试程序比较几种内部排序算法的关键字比较次数和移动次数以取得直观感受。 2.4运行环境 (1)WINDOWSXP系统 (2)C++ 编译环境 3.实验方法 本实验主要是内排序,通过比较的次数和移动的次数判断排序的好坏。主要子函数的说明如下。 1.简单选择排序XuanzePaixu(); 2.冒泡排序MaopaoPaixu(); 3. 直接插入排序CharuPaixu(); 4. 快速排序KuaisuPaixu(); 5. 堆排序DuiPaixu(); 6. 希尔排序 XierPaixu(); 以上的排序算法均采用书中所用的算法。程序采用输入的时候仅输入所要的个数,具体的输入数据由程序随机产生个数,并且输出。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

我慢慢地也过来了

谢谢大佬的投喂

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

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

打赏作者

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

抵扣说明:

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

余额充值