实验三、排序
算法实验报告

算法实验报告算法实验报告引言:算法是计算机科学的核心内容之一,它是解决问题的方法和步骤的描述。
算法的设计和分析是计算机科学与工程中的重要研究方向之一。
本实验旨在通过对算法的实际应用和实验验证,深入理解算法的性能和效果。
实验一:排序算法的比较在本实验中,我们将比较三种常见的排序算法:冒泡排序、插入排序和快速排序。
我们将通过对不同规模的随机数组进行排序,并记录每种算法所需的时间和比较次数,以评估它们的性能。
实验结果显示,快速排序是最快的排序算法,其时间复杂度为O(nlogn),比较次数也相对较少。
插入排序的时间复杂度为O(n^2),比较次数较多,但对于小规模的数组排序效果较好。
而冒泡排序的时间复杂度也为O(n^2),但比较次数更多,效率相对较低。
实验二:图的最短路径算法在图的最短路径问题中,我们将比较Dijkstra算法和Floyd-Warshall算法的效率和准确性。
我们将使用一个带权有向图,并计算从一个顶点到其他所有顶点的最短路径。
实验结果表明,Dijkstra算法适用于单源最短路径问题,其时间复杂度为O(V^2),其中V为顶点数。
而Floyd-Warshall算法适用于多源最短路径问题,其时间复杂度为O(V^3)。
两种算法在准确性上没有明显差异,但在处理大规模图时,Floyd-Warshall算法的效率较低。
实验三:动态规划算法动态规划是一种通过将问题分解成子问题并记录子问题的解来解决复杂问题的方法。
在本实验中,我们将比较两种动态规划算法:0-1背包问题和最长公共子序列问题。
实验结果显示,0-1背包问题的动态规划算法可以有效地找到最优解,其时间复杂度为O(nW),其中n为物品个数,W为背包容量。
最长公共子序列问题的动态规划算法可以找到两个序列的最长公共子序列,其时间复杂度为O(mn),其中m和n分别为两个序列的长度。
结论:通过本次实验,我们对不同算法的性能和效果有了更深入的了解。
排序算法中,快速排序是最快且效率最高的;在图的最短路径问题中,Dijkstra算法和Floyd-Warshall算法分别适用于不同的场景;动态规划算法可以解决复杂的问题,并找到最优解。
排序的实验报告册

一、实验目的1. 了解排序算法的基本原理和常用算法。
2. 掌握几种常用排序算法的代码实现。
3. 比较不同排序算法的性能,分析其优缺点。
4. 培养实验操作能力和分析问题能力。
二、实验环境1. 操作系统:Windows 102. 编程语言:Python3.73. 开发工具:PyCharm三、实验内容1. 实验一:冒泡排序2. 实验二:选择排序3. 实验三:插入排序4. 实验四:快速排序5. 实验五:归并排序四、实验步骤1. 实验一:冒泡排序(1)编写冒泡排序的Python代码。
(2)对一组随机生成的数据进行排序。
(3)观察排序过程,分析冒泡排序的优缺点。
2. 实验二:选择排序(1)编写选择排序的Python代码。
(2)对一组随机生成的数据进行排序。
(3)观察排序过程,分析选择排序的优缺点。
3. 实验三:插入排序(1)编写插入排序的Python代码。
(2)对一组随机生成的数据进行排序。
(3)观察排序过程,分析插入排序的优缺点。
4. 实验四:快速排序(1)编写快速排序的Python代码。
(2)对一组随机生成的数据进行排序。
(3)观察排序过程,分析快速排序的优缺点。
5. 实验五:归并排序(1)编写归并排序的Python代码。
(2)对一组随机生成的数据进行排序。
(3)观察排序过程,分析归并排序的优缺点。
五、实验结果与分析1. 实验一:冒泡排序(1)代码实现:```pythondef bubble_sort(arr):n = len(arr)for i in range(n):for j in range(0, n-i-1):if arr[j] > arr[j+1]:arr[j], arr[j+1] = arr[j+1], arr[j]```(2)排序过程:冒泡排序通过比较相邻两个元素的大小,将较大的元素向后移动,从而实现排序。
(3)优缺点分析:优点:易于理解,实现简单。
缺点:时间复杂度较高,对于大数据量排序效率较低。
数据结构实验报告-排序

数据结构实验报告-排序一、实验目的本实验旨在探究不同的排序算法在处理大数据量时的效率和性能表现,并对比它们的优缺点。
二、实验内容本次实验共选择了三种常见的排序算法:冒泡排序、快速排序和归并排序。
三个算法将在同一组随机生成的数据集上进行排序,并记录其性能指标,包括排序时间和所占用的内存空间。
三、实验步骤1. 数据的生成在实验开始前,首先生成一组随机数据作为排序的输入。
定义一个具有大数据量的数组,并随机生成一组在指定范围内的整数,用于后续排序算法的比较。
2. 冒泡排序冒泡排序是一种简单直观的排序算法。
其基本思想是从待排序的数据序列中逐个比较相邻元素的大小,并依次交换,从而将最大(或最小)的元素冒泡到序列的末尾。
重复该过程直到所有数据排序完成。
3. 快速排序快速排序是一种分治策略的排序算法,效率较高。
它将待排序的序列划分成两个子序列,其中一个子序列的所有元素都小于等于另一个子序列的所有元素。
然后对两个子序列分别递归地进行快速排序。
4. 归并排序归并排序是一种稳定的排序算法,使用分治策略将序列拆分成较小的子序列,然后递归地对子序列进行排序,最后再将子序列合并成有序的输出序列。
归并排序相对于其他算法的优势在于其稳定性和对大数据量的高效处理。
四、实验结果经过多次实验,我们得到了以下结果:1. 冒泡排序在数据量较小时,冒泡排序表现良好,但随着数据规模的增大,其性能明显下降。
排序时间随数据量的增长呈平方级别增加。
2. 快速排序相比冒泡排序,快速排序在大数据量下的表现更佳。
它的排序时间线性增长,且具有较低的内存占用。
3. 归并排序归并排序在各种数据规模下都有较好的表现。
它的排序时间与数据量呈对数级别增长,且对内存的使用相对较高。
五、实验分析根据实验结果,我们可以得出以下结论:1. 冒泡排序适用于数据较小的排序任务,但面对大数据量时表现较差,不推荐用于处理大规模数据。
2. 快速排序是一种高效的排序算法,适用于各种数据规模。
排序基本算法实验报告

一、实验目的1. 掌握排序算法的基本原理和实现方法。
2. 熟悉常用排序算法的时间复杂度和空间复杂度。
3. 能够根据实际问题选择合适的排序算法。
4. 提高编程能力和问题解决能力。
二、实验内容1. 实现并比较以下排序算法:冒泡排序、插入排序、选择排序、快速排序、归并排序、堆排序。
2. 对不同数据规模和不同数据分布的序列进行排序,分析排序算法的性能。
3. 使用C++编程语言实现排序算法。
三、实验步骤1. 冒泡排序:将相邻元素进行比较,如果顺序错误则交换,直到序列有序。
2. 插入排序:将未排序的元素插入到已排序的序列中,直到序列有序。
3. 选择排序:每次从剩余未排序的元素中选取最小(或最大)的元素,放到已排序序列的末尾。
4. 快速排序:选择一个枢纽元素,将序列分为两部分,一部分比枢纽小,另一部分比枢纽大,递归地对两部分进行排序。
5. 归并排序:将序列分为两半,分别对两半进行排序,然后将两半合并为一个有序序列。
6. 堆排序:将序列构建成一个最大堆,然后依次取出堆顶元素,最后序列有序。
四、实验结果与分析1. 冒泡排序、插入排序和选择排序的时间复杂度均为O(n^2),空间复杂度为O(1)。
这些算法适用于小规模数据或基本有序的数据。
2. 快速排序的时间复杂度平均为O(nlogn),最坏情况下为O(n^2),空间复杂度为O(logn)。
快速排序适用于大规模数据。
3. 归并排序的时间复杂度和空间复杂度均为O(nlogn),适用于大规模数据。
4. 堆排序的时间复杂度和空间复杂度均为O(nlogn),适用于大规模数据。
五、实验结论1. 根据不同数据规模和不同数据分布,选择合适的排序算法。
2. 冒泡排序、插入排序和选择排序适用于小规模数据或基本有序的数据。
3. 快速排序、归并排序和堆排序适用于大规模数据。
4. 通过实验,加深了对排序算法的理解,提高了编程能力和问题解决能力。
六、实验总结本次实验通过对排序算法的学习和实现,掌握了常用排序算法的基本原理和实现方法,分析了各种排序算法的性能,提高了编程能力和问题解决能力。
排序的实验报告

排序的实验报告排序的实验报告引言:排序是计算机科学中非常重要的一个概念,它涉及到对一组数据按照一定规则进行重新排列的操作。
在计算机算法中,排序算法的效率直接影响到程序的运行速度和资源利用率。
为了深入了解各种排序算法的原理和性能,我们进行了一系列的排序实验。
实验一:冒泡排序冒泡排序是最简单的排序算法之一。
它的原理是通过相邻元素的比较和交换来实现排序。
我们编写了一个冒泡排序的算法,并使用Python语言进行实现。
实验中,我们分别对10、100、1000个随机生成的整数进行排序,并记录了排序所需的时间。
实验结果显示,随着数据规模的增加,冒泡排序的时间复杂度呈现出明显的增长趋势。
当数据规模为10时,排序所需的时间约为0.001秒;而当数据规模增加到1000时,排序所需的时间则增加到了1.5秒左右。
这说明冒泡排序的效率较低,对大规模数据的排序并不适用。
实验二:快速排序快速排序是一种常用的排序算法,它的核心思想是通过分治的策略将数据分成较小的子集,然后递归地对子集进行排序。
我们同样使用Python语言实现了快速排序算法,并对相同规模的数据进行了排序实验。
实验结果显示,快速排序的时间复杂度相对较低。
当数据规模为10时,排序所需的时间约为0.0005秒;而当数据规模增加到1000时,排序所需的时间仅为0.02秒左右。
这说明快速排序适用于大规模数据的排序,其效率较高。
实验三:归并排序归并排序是一种稳定的排序算法,它的原理是将待排序的数据分成若干个子序列,然后将子序列两两合并,直到最终得到有序的结果。
我们同样使用Python 语言实现了归并排序算法,并进行了相同规模数据的排序实验。
实验结果显示,归并排序的时间复杂度相对较低。
当数据规模为10时,排序所需的时间约为0.0008秒;而当数据规模增加到1000时,排序所需的时间仅为0.03秒左右。
这说明归并排序同样适用于大规模数据的排序,其效率较高。
讨论与结论:通过以上实验,我们可以得出以下结论:1. 冒泡排序虽然简单易懂,但对于大规模数据的排序效率较低,不适用于实际应用。
排序的实验报告

排序的实验报告排序的实验报告引言:排序是计算机科学中常见的问题之一。
在实际应用中,我们经常需要对一组数据进行排序,以便更好地理解和分析数据。
本实验旨在比较不同排序算法的效率和性能,以及探讨它们在不同数据集上的表现。
实验设计:为了进行排序算法的比较,我们选择了五种常见的排序算法,分别是冒泡排序、选择排序、插入排序、快速排序和归并排序。
我们使用Python编程语言实现了这些算法,并在同一台计算机上运行它们以确保公平比较。
实验步骤:1. 数据集的准备我们选择了三种不同规模的数据集:小规模(100个元素)、中规模(1000个元素)和大规模(10000个元素)。
这些数据集包含了随机生成的整数。
2. 算法实现我们按照上述算法的描述,使用Python编程语言实现了这些排序算法。
为了确保准确性和效率,我们在实现过程中进行了多次测试和调试。
3. 实验运行我们分别对小规模、中规模和大规模的数据集运行这些排序算法,并记录下每个算法的运行时间。
实验结果:1. 小规模数据集排序结果对于小规模的数据集,所有的排序算法都能够在很短的时间内完成排序。
然而,快速排序和归并排序的运行时间明显短于冒泡排序、选择排序和插入排序。
2. 中规模数据集排序结果随着数据规模的增加,冒泡排序、选择排序和插入排序的运行时间显著增加,而快速排序和归并排序的运行时间仍然较短。
特别是在中规模数据集上,快速排序和归并排序的效率明显高于其他算法。
3. 大规模数据集排序结果在大规模数据集上,冒泡排序、选择排序和插入排序的运行时间急剧增加,而快速排序和归并排序的运行时间仍然保持在可接受的范围内。
这进一步证明了快速排序和归并排序的高效性。
讨论:通过对不同规模数据集的排序实验,我们可以得出以下结论:1. 快速排序和归并排序是最有效的排序算法,它们的运行时间相对较短。
2. 冒泡排序、选择排序和插入排序在小规模数据集上表现良好,但在大规模数据集上效率较低。
3. 对于特定的应用场景,选择合适的排序算法非常重要。
排序的应用实验报告
排序的应用实验报告实验题目:排序的应用实验一、实验目的:1. 了解排序算法的基本原理和应用场景;2. 掌握常见的排序算法的实现方法;3. 熟悉排序算法的时间复杂度分析;4. 在实际应用中灵活运用排序算法。
二、实验原理:排序是将一组数据按照某个规则进行重新排列的过程,常见的排序算法有冒泡排序、选择排序、插入排序、归并排序、快速排序、堆排序等。
每种排序算法有其特点和适用场景,掌握不同排序算法的实现方法和时间复杂度对于实际应用非常重要。
三、实验内容及步骤:1. 冒泡排序实验:a) 随机生成一组整数数据;b) 利用冒泡排序算法对数据进行排序;c) 输出排序结果,并统计排序过程中的比较次数和交换次数。
2. 选择排序实验:a) 随机生成一组整数数据;b) 利用选择排序算法对数据进行排序;c) 输出排序结果,并统计排序过程中的比较次数和交换次数。
3. 插入排序实验:a) 随机生成一组整数数据;b) 利用插入排序算法对数据进行排序;c) 输出排序结果,并统计排序过程中的比较次数和移动次数。
4. 归并排序实验:a) 随机生成一组整数数据;b) 利用归并排序算法对数据进行排序;c) 输出排序结果。
5. 快速排序实验:a) 随机生成一组整数数据;b) 利用快速排序算法对数据进行排序;c) 输出排序结果。
四、实验结果及分析:1. 冒泡排序实验结果:随机生成的一组整数数据为:[5, 3, 8, 2, 6]排序过程中的比较次数为:10排序过程中的交换次数为:4排序结果为:[2, 3, 5, 6, 8]2. 选择排序实验结果:随机生成的一组整数数据为:[5, 3, 8, 2, 6] 排序过程中的比较次数为:10排序过程中的交换次数为:4排序结果为:[2, 3, 5, 6, 8]3. 插入排序实验结果:随机生成的一组整数数据为:[5, 3, 8, 2, 6] 排序过程中的比较次数为:10排序过程中的移动次数为:7排序结果为:[2, 3, 5, 6, 8]4. 归并排序实验结果:随机生成的一组整数数据为:[5, 3, 8, 2, 6] 排序结果为:[2, 3, 5, 6, 8]5. 快速排序实验结果:随机生成的一组整数数据为:[5, 3, 8, 2, 6]排序结果为:[2, 3, 5, 6, 8]五、实验总结:通过本次实验,我对常见的排序算法有了更深入的了解。
实验三 快速排序与归并排序 matlab
实验项目——快速排序法11信本一、上机目的及内容1.上机内容用快速排序法对任意一组无序数据排序。
2.上机目的掌握并应用算法的数学分析,后验分析方法及matlab的使用。
二、实验要求1. 对所设计的算法采用大O符号进行时间复杂性分析;2.上机实现算法,并用计数法和计时法分别测算算法的运行时间;三、所用仪器、材料(设备名称、型号、规格等或使用软件)1台PC及matlab .2008四、实验方法、步骤(或:程序代码或操作过程)以第一个记录作为轴值,对待排序序列进行划分的过程为:(1)初始化:取第一个记录作为基准,设置两个参数i,j分别用来指示将要与基准记录进行比较的左侧记录位置和右侧记录位置,也就是本次划分的区间;(2)右侧扫描过程:将基准记录与j指向的记录进行比较,如果j 指向记录的关键码大,则j前移一个记录位置。
重复右侧扫描过程,直到右侧的记录小(即反序),若i<j,则将基准记录与j指向的记录进行交换;(3)左侧扫描过程:将基准记录与i指向的记录进行比较,如果i 指向记录的关键码小,则i后移一个记录位置。
重复左侧扫描过程,直到左侧的记录大(即反序),若i<j,则将基准记录与i指向的记录交换;(4)重复(2)(3)步,直到i 与j 指向同一位置,即基准记录最终的位置。
在最好情况下,每次划分对一个记录定位后,该记录的左侧子序列与右侧子序列的长度相同。
在具有n 个记录的序列中,一次划分需要对整个待划分序列扫描一遍,则所需时间为O(n)。
设T(n)是对n 个记录的序列进行排序的时间,每次划分后,正好把待划分区间划分为长度相等的两个子序列,则有:T(n)≤2 T(n/2)+n≤2(2T(n/4)+n/2)+n =4T(n/4)+2n≤4(2T(n/8)+n/4)+2n =8T(n/8)+3n… … …≤nT(1)+nlog2n =O(nlog2n)因此,时间复杂度为O(nlog2n)。
在最坏情况下,待排序记录序列正序或逆序,每次划分只得到一个比上一次划分少一个记录的子序列(另一个子序列为空)。
实验三、交换标志位法排序
实验名称:三、数据块排序实验日期:2010.5.29得分:同组人:不填指导教师:马惠兰一、实验目的1.熟练掌握Keil uvision3单片机仿真软件的使用方法。
2.进一步熟悉单片机实验操作步骤。
3.掌握分别用双循环法、交换标志位法和求极值法实现数据块排序的编程方法和技巧。
4.掌握Keil uvision3软件内RAM单元数据查看和修改的命令和方法。
二、实验设备PC机一台三、实验内容在起始地址为60H的内RAM数据存储区中,连续存放有10个无符号数,编程将其由大到小排序。
四、实验原理本人采用交换标志位法实现上述实验内容。
用交换标志位法实现无符号数据块排序,需要设置一个交换标志位,实验中选择PSW的b5位——F0,F0=0表示数据比较大小时没有交换,F0=1表示数据比较大小时有交换。
循环初始化置F0为0,第1次大循环数据块中的10数据两两比较9次,两个数据比较大小,若第一个数大于第二个数,则不变,若第一个数小于第二个数,则交换,并且置F0=1;这样比较到最后,最后一个单元中存放的应该是参加排序的数据块中最小的数据。
然后判断F0的状态,若F0=0,则说明一次交换都没有,数据块已经排好序了;若F0=1,则说明至少有一次交换,数据块还没有排好序,需要继续进行排序操作。
第2次大循环时,F0又置初值0,但参加排序的数据只有9个(10个数据中的最小数已经排在了最后一个单元),循环次数变成了8次,循环结束后同样判断F0的状态,以判断数据块是否排好序,是否再进行排序操作。
如此循环,直到某一次大循环结束后,判断发现F0为0时,则说明数据块排好序了。
用交换标志位法实现无符号数据块排序,必须注意一种情况,就是最后只剩下最上面的两个数据排序时,若比较后交换标志位F0=1,排序也结束,因为所有数据都排序好了。
这种情况两个数据的比较次数等于用双循环法排序时两个数据的比较次数。
根据此实验原理编写的实验源程序清单见附页。
五、实验步骤1.在F盘下为工程建立文件夹马惠兰3;2.新建工程项目文件马惠兰3.uv2,保存在文件夹马惠兰3中,并为工程选择目标器件为SST89E554RC;3.编辑源程序,建立源文件马惠兰3.ASM,保存在文件夹马惠兰3中;4.将源文件马惠兰3.ASM添加到工程项目组中;5.设置调试环境,选择调试模式为软件模拟;6.加载程序,打开存储器窗口,在地址栏中输入:“D:60H”回车,修改内RAM60H单元开始的10个单元数据,运行程序,根据预习设计的数据记录表格记录实验数据;7.修改源程序,将指令“JNC NEXT”改为“JC NEX T”,保存、汇编后重新加载运行程序,记录实验数据;8.实验数据经过实验指导教师检查正确后,实验结束。
排序实验报告
实验五排序实验目的: 掌握几种排序的思想及算法问题分析:(一)直接插入排序1. 排序思想将待排序的记录Ri,插入到已排好序的记录表R1, R2 ,…., Ri-1中,得到一个新的、记录数增加1的有序表。
直到所有的记录都插入完为止。
设待排序的记录顺序存放在数组R[1…n]中,在排序的某一时刻,将记录序列分成两部分:◆R[1…i-1]:已排好序的有序部分;◆R[i…n]:未排好序的无序部分。
显然,在刚开始排序时,R[1]是已经排好序的。
2 . 算法实现void straight_insert_sort(Sqlist R){ int i, j ;for (i=2; i<=n; i++){ R[0]=R[i]; j=i-1; /*设置哨兵*/while( LT(R[0].key, R[j].key) ){ R[j+1]=R[j];j--;} /* 查找插入位置*/R[j+1]=R[0]; /* 插入到相应位置*/}}(二)希尔排序1. 排序思想①先取一个正整数d1(d1<n)作为第一个增量,将全部n个记录分成d1组,把所有相隔d1的记录放在一组中,即对于每个k(k=1, 2, … d1),R[k], R[d1+k], R[2d1+k] , …分在同一组中,在各组内进行直接插入排序。
这样一次分组和排序过程称为一趟希尔排序;②取新的增量d2<d1,重复①的分组和排序操作;直至所取的增量di=1为止,即所有记录放进一个组中排序为止。
2. 算法实现先给出一趟希尔排序的算法,类似直接插入排序。
void shell_pass(Sqlist R, int d)/* 对顺序表L进行一趟希尔排序, 增量为d */{ int j, k ;for (j=d+1; j<=n; j++){ R[0]=R[j] ; /* 设置监视哨兵*/k=j-d ;while (k>0&<(R[0].key, R[k].key) ){ R[k+d]=R[k] ; k=k-d ; }R[k+d]=R[0] ;}}然后在根据增量数组dk进行希尔排序。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
实验三、排序一、目的掌握各种排序方法的基本思想、排序过程、算法实现,能进行时间和空间性能的分析,根据实际问题的特点和要求选择合适的排序方法。
二、要求实现直接排序、冒泡、直接选择、快速、堆、归并排序算法。
比较各种算法的运行速度。
三、程序示例#include"stdio.h"#include"stdlib.h"#define Max 100 //假设文件长度typedef struct{ //定义记录类型int key; //关键字项}RecType;typedef RecType SeqList[Max+1]; //SeqList为顺序表,表中第0个元素作为哨兵int n; //顺序表实际的长度1、直接插入排序的基本思想:每次将一个待排序的记录,按其关键字大小插入到前面已排序好的子文件中的适当位置,直到全部记录插入完成为止。
//==========直接插入排序法======void InsertSort(SeqList R){ //对顺序表R中的记录R[1‥n]按递增序进行插入排序int i,j;for(i=2;i<=n;i++) //依次插入R[2],……,R[n]if(R[i].key<R[i-1].key){ //若R[i].key大于等于有序区中所有的keys,则R[i]留在原位 R[0]=R[i];j=i-1; //R[0]是R[i]的副本do { //从右向左在有序区R[1‥i-1]中查找R[i] 的位置R[j+1]=R[j]; //将关键字大于R[i].key的记录后移j--;}while(R[0].key<R[j].key); //当R[i].key≥R[j].key 是终止R[j+1]=R[0]; //R[i]插入到正确的位置上}//endif}2、冒泡排序的基本思想:设想被排序的记录数组R[1‥n]垂直排序。
根据轻气泡不能在重气泡之下的原则,从下往上扫描数组R,凡扫描到违反本原则的轻气泡,就使其向上“漂浮”(交换),如此反复进行,直到最后任意两个气泡都是轻者在上,重者在下为止。
//==========冒泡排序=======typedef enum{FALSE,TRUE} Boolean; //FALSE为0,TRUE为1void BubbleSort(SeqList R){ //自下向上扫描对R做冒泡排序int i,j;Boolean exchange; //交换标志for(i=1;i<n;i++) { //最多做n-1趟排序exchange=FALSE; //本趟排序开始前,交换标志应为假for(j=n-1;j>=i;j--) //对当前无序区R[i‥n] 自下向上扫描if(R[j+1].key<R[j].key){ //两两比较,满足条件交换记录R[0]=R[j+1]; //R[0]不是哨兵,仅做暂存单元R[j+1]=R[j];R[j]=R[0];exchange=TRUE; //发生了交换,故将交换标志置为真}if(! exchange) //本趟排序未发生交换,提前终止算法return;}// endfor(为循环)}3、快速排序的基本思想:在待排序的n个记录中任取一个记录(通常取第一个记录),把该记录作为支点(又称基准记录)(pivot),将所有关键字比它小的记录放置在它的位置之前,将所有关键字比它大的记录放置在它的位置之后(称之为一次划分过程)。
之后对所分的两部分分别重复上述过程,直到每部分只有一个记录为止。
//1.========一次划分函数=====int Partition(SeqList R,int i,int j){ // 对R[i‥j]做一次划分,并返回基准记录的位置RecType pivot=R[i]; //用第一个记录作为基准while(i<j) { //从区间两端交替向中间扫描,直到i=jwhile(i<j &&R[j].key>=pivot.key) //基准记录pivot相当与在位置i上j--; //从右向左扫描,查找第一个关键字小于pivot.key的记录R[j]if(i<j) //若找到的R[j].key < pivot.key,则R[i++]=R[j]; //交换R[i]和R[j],交换后i指针加1while(i<j &&R[i].key<=pivot.key) //基准记录pivot相当与在位置j上i++; //从左向右扫描,查找第一个关键字小于pivot.key的记录R[i]if(i<j) //若找到的R[i].key > pivot.key,则R[j--]=R[i]; //交换R[i]和R[j],交换后j指针减1}R[i]=pivot; //此时,i=j,基准记录已被最后定位return i; //返回基准记录的位置}//2.=====快速排序===========void QuickSort(SeqList R,int low,int high){ //R[low..high]快速排序int pivotpos; //划分后基准记录的位置if(low<high) { //仅当区间长度大于1时才排序pivotpos=Partition(R,low,high); //对R[low..high]做一次划分,得到基准记录的位置QuickSort(R,low,pivotpos-1); //对左区间递归排序QuickSort(R,pivotpos+1,high); //对右区间递归排序}4、直接选择排序的基本思想:第i趟排序开始时,当前有序区和无序区分别为R[1‥i-1]和R[i‥n](1≤i≤n-1),该趟排序则是从当前无序区中选择出关键字最小的记录R[k],将它与无序区的的第一个记录R[i]交换,有序区增加一个记录,使R[1‥i],和R[i+1‥n]分别为新的有序区和新的无序区。
如此反复进行,直到排序完毕。
//======直接选择排序========void SelectSort(SeqList R){int i,j,k;for(i=1;i<n;i++){ //做第i趟排序(1≤i≤n-1)k=i;for(j=i+1;j<=n;j++) //在当前无序区R[i‥n]中选key最小的记录R[k] if(R[j].key<R[k].key)k=j; //k记下目前找到的最小关键字所在的位置if(k!=i) { // //交换R[i]和R[k]R[0]=R[i];R[i]=R[k];R[k]=R[0];} //endif} //endfor}5、堆排序的基本思想:它是一种树型选择排序,特点是:在排序的过程中,将R[1‥n]看成是一个完全二叉树的顺序存储结构,利用完全二叉树中双亲结点和孩子结点之间的内在关系,在当前无序区中选择关键字最大(或最小)的记录。
即:把待排序文件的关键字存放在数组R[1‥n]子中,将R看成是一棵二叉树,每个结点表示一个记录,源文件的第一个记录R[1]作为二叉树的根,以下各记录R[2‥n]依次逐层从左到右排列,构成一棵完全二叉树,任意结点R[i]的左孩子是R[2i],右孩子是R[2i+1],双亲是R[i/2]。
对这棵完全二叉树的结点进行调整,使各结点的关键字满足下列条件:R[i].key≤R[2i].key并且R[i].key≤R[2i+1].key 称小堆根或R[i].key≥R[2i].key并且R[i].key≥R[2i+1].key 称大堆根//==========大根堆调整函数=======void Heapify(SeqList R,int low,int high){ // 将R[low..high]调整为大根堆,除R[low]外,其余结点均满足堆性质int large; //large指向调整结点的左、右孩子结点中关键字较大者RecType temp=R[low]; //暂存调整结点for(large=2*low; large<=high;large*=2){ //R[low]是当前调整结点//若large>high,则表示R[low]是叶子,调整结束;否则先令large指向R[low]的左孩子if(large<high && R[large].key<R[large+1].key)large++; //若R[low]的右孩子存在且关键字大于左兄弟,则令large指向它//现在R[large]是调整结点R[low]的左右孩子结点中关键字较大者if(temp.key>=R[large].key) //temp始终对应R[low]break; //当前调整结点不小于其孩子结点的关键字,结束调整R[low]=R[large]; //相当于交换了R[low]和R[large]low=large; //令low指向新的调整结点,相当于temp已筛下到large的位置}R[low]=temp; //将被调整结点放入最终位置上//==========构造大根堆==========void BuildHeap(SeqList R){ //将初始文件R[1..n]构造为堆int i;for(i=n/2;i>0;i--)Heapify(R,i,n); //将R[i..n]调整为大根堆}//==========堆排序===========void HeapSort(SeqList R){ //对R[1..n]进行堆排序,不妨用R[0]做暂存单元int i;BuildHeap(R); //将R[1..n]构造为初始大根堆for(i=n;i>1;i--){ //对当前无序区R[1..i]进行堆排序,共做n-1趟。
R[0]=R[1]; R[1]=R[i];R[i]=R[0]; //将堆顶和堆中最后一个记录交换Heapify(R,1,i-1); //将R[1..i-1]重新调整为堆,仅有R[1]可能违反堆性质。
}}6、二路归并排序的基本思想:假设初始序列n个记录,则可看成是n个有序的子序列,每个子序列的长度为1,然后两两归并,得到[n/2]个长度为2或1的有序子序列;再两两归并,……,如此重复,直到一个长度为n的有序序列为止。
//=====将两个有序的子序列R[low..m]和R[m+1..high]归并成有序的序列R[low..high]== void Merge(SeqList R,int low,int m,int high){int i=low,j=m+1,p=0; //置初始值RecType *R1; //R1为局部量R1=(RecType *)malloc((high-low+1)*sizeof(RecType)); //申请空间while(i<=m && j<=high) //两个子序列非空时取其小者输出到R1[p]上R1[p++]=(R[i].key<=R[j].key)? R[i++]:R[j++];while(i<=m) //若第一个子序列非空,则复制剩余记录到R1R1[p++]=R[i++];while(j<=high) //若第二个子序列非空,则复制剩余记录到R1中R1[p++]=R[j++];for(p=0,i=low;i<=high;p++,i++)R[i]=R1[p]; //归并完成后将结果复制回R[low..high]}//=========对R[1..n]做一趟归并排序========void MergePass(SeqList R,int length){int i;for(i=1;i+2*length-1<=n;i=i+2*length)Merge(R,i,i+length-1,i+2*length-1); //归并长度为length的两个相邻的子序列if(i+length-1<n) //尚有一个子序列,其中后一个长度小于lengthMerge(R,i,i+length-1,n); //归并最后两个子序列//注意:若i≤n且i+length-1≥n时,则剩余一个子序列轮空,无须归并}//========== 自底向上对R[1..n]做二路归并排序===============void MergeSort(SeqList R){int length;for(length=1;length<n;length*=2) //做[lgn]趟排序MergePass(R,length); //有序长度≥n时终止}//==========输入顺序表========void input_int(SeqList R){int i;printf("Please input num(int):");scanf("%d",&n);printf("Plase input %d integer:",n);for(i=1;i<=n;i++)scanf("%d",&R[i].key);}//==========输出顺序表========void output_int(SeqList R){int i;for(i=1;i<=n;i++)printf("%4d",R[i].key);}//==========主函数======void main(){int i;SeqList R;input_int(R);printf("\t******** Select **********\n");printf("\t1: Insert Sort\n");printf("\t2: Bubble Sort\n");printf("\t3: Quick Sort\n");printf("\t4: Straight Selection Sort\n");printf("\t5: Heap Sort\n");printf("\t6: Merge Sort\n");printf("\t7: Exit\n");printf("\t***************************\n");scanf("%d",&i); //输入整数1-7,选择排序方式switch (i){case 1: InsertSort(R); break; //值为1,直接插入排序case 2: BubbleSort(R); break; //值为2,冒泡法排序case 3: QuickSort(R,1,n); break; //值为3,快速排序case 4: SelectSort(R); break; //值为4,直接选择排序case 5: HeapSort(R); break; //值为5,堆排序case 6: MergeSort(R); break; //值为6,归并排序case 7: exit(0); //值为7,结束程序}printf("Sort reult:");output_int(R);}四、实验内容1、分析、理解程序。