实验时间 | 2024年 4 月10日19时至22时 | 学时数 | 3 | ||
1.实验名称 分治与减治算法实验:题目2 排序中分治法的程序设计 | |||||
2.实验目的 (1)掌握归并排序和快速排序的划分方法; (2)掌握归并排序和快速排序的具体分治策略; (3)在掌握的基础上编程两种排序方法的实现过程。 | |||||
3.实验内容 给出一个初始序列,分别用归并排序和快速排序两种分治法将所给序列变换为有序序列,输出结果,输出时要求有文字说明。请任选一种语言编写程序实现上述算法,并分析其算法复杂度。 | |||||
【原理1】应用归并排序方法对一个记录序列进行升序排列。归并排序(merge sort)的分治策略如图所示,描述如下。 (1)划分:将待排序序列r1,r2,…,rn划分为两个长度相等的子序列r1,…,rn/2和rn/2+1,…,rn。 (2)求解子问题:分别对这两个子序列进行排序,得到两个有序子序列。 (3)合并:将这两个有序子序列合并成一个有序序列。 ![]() 归并排序的分治思想 【原理2】应用快速排序方法对一个记录序列进行升序排列。快速排序(quick sort)的分治策略如下,如图所示。 (1)划分:选定一个记录作为轴值,以轴值为基准将整个序列划分为两个子序列r1…ri-1和 ri+1…rn,轴值的位置i在划分的过程中确定,并且前一个子序列中的记录均小于或等于轴值,后一个子序列中的记录均大于或等于轴值。 (2)求解子问题:分别对划分后的每一个子序列递归处理。 (3)合并:由于对子序列r1…ri-1和ri+1…rn的排序是就地进行的,所以合并不需要执行任何操作。 ![]() 快速排序的分治思想 | |||||
9.实验源代码和伪代码 设对数组r[n]进行升序排序排列,归并排序的递归算法用伪代码描述如下:
设将两个相邻的有序子序列r[s]~r[m]和r[m+1]~r[t]合并为一个有序序列rl[s]~rl[t],函数Merge实现合并操作。归并排序算法用C++语言描述如下:
设函数Partition实现对序列r[first]~r[end]进行划分,快速排序对各个子序列的排序是就地进行,不需要合并子问题的解。快速排序算法用C++语言描述如下:
时间复杂度分析: 归并排序: 设待排序记录个数为n,则执行一趟合并算法的时间复杂性为O(n),所以,归并排序算法存在如下递推式: ![]() 根据主定理,归并排序的时间代价是O(nlog2n)。 归并排序的合并步需要将两个相邻的有序子序列合并为一个有序序列,在合并过程中可能会破坏原来的有序序列,所以,合并不能就地进行。归并排序需要与待排序记录序列同样数量的存储空间,以便存放归并结果,因此其空间复杂性为O(n)。 1.如果。等于t,则待排序区间只有一个记录,算法结束; 2.计算划分中点:m=(s+D/2; 3.对前半个子序列r[s]~r[m]进行升序排列: 4.对后半个子序列r[m+1]~r[]进行升序排列; 5.合并两个升序序列r[s]~r[m]和r[m+1]~r[t]: 快速排序: 最好情况下,每次划分对一个记录定位后,该记录的左侧子序列与右侧子序列的长度相同。在具有n个记录的序列中,一次划分需要对整个待划分序列扫描一遍,则所需时间为O(n)。设T(n)是对n个记录的序列进行排序的时间,每次划分后,正好把待划分区间划分为长度相等的两个子序列,则有: T(n)=2T(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) 最坏情况下,待排序记录序列正序或逆序,每次划分只得到一个比上一次划分少一个记录的子序列(另一个子序列为空)。此时,必须经过n-1次递归调用才能把所有记录定位而且第i趟划分需要经过n-i次比较才能找到第i个记录的位置,因此,时间复杂性为: ![]() n(n-1)=O(n2) 平均情况下,设轴值记录的关键码第k小(1≤k≤n),则有: ![]() 这是快速排序的平均时间性能,可以用归纳法证明,其数量级也为O(nlog2n)。 | |||||
代码运行截图: 归并排序: ![]() 快速排序: ![]() 心得: 补充了新的排序方法。 |
分治与减治算法实验:题目2 排序中分治法的程序设计
于 2024-04-15 12:28:40 首次发布
![](https://img-home.csdnimg.cn/images/20240711042549.png)