数据结构课程设计二路归并排序说明书
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
前言
1.1排序的重要性
生活中,无时不刻不充满这排序,比如:班级同学的成绩排名问题,公司产值高低的问题等等,解决这些问题的过程中,都涉及到了一个数据结构的构造思想过程。数据结构中的排序,也有很多种,如:插入排序、交换排序、选择排序等等,此时我们就要注意选择具有优解的算法,将一个数据元素(或记录)的任意序列,重新排列成一个有序的排列,便于我们查找。
假设含有n个记录的序列为{R1,R2,Rn},其相应的关键字序列为{K1,K2,…,Kn}需确定1,2…n的一种排序P1,P2…Pn,使其相应的关键字满足如下的非递减的关系:Kp1≤Kp2≤…≤Kpn,即按关键字{Rp1,Rp2,…,Rpn}有序的排列,这样的一种操作称为排序。一般情况下,排序又分为内部排序和外部排序。而在内部排序中又含有很多排序方法,就其全面性能而言,很难提出一种被认为是最好的方法,因为每一种方法都有它的优缺点,适合在不同的环境下使用。我们学习的排序有:直接插入排序、折半插入排序、希尔排序、快速排序、基数排序、归并排序等。本次课题研究中,我主要进行了二路归并排序的研究和学习。
1.2设计的背景和意义
排序是计算机领域的一类非常重要的问题,计算机在出来数据的过程中,有25%的时间花在了排序上,有许多的计算机设备,排序用去计算机处理数据时间的一半以上,这对于提高计算机的运行速度有一定的影响。此时排序算法的高效率显得尤为重要。
在排序算法汇中,归并排序(Merging sort)是与插入排序、交换排序、选择排序不同的另一类排序方法。归并的含义是将两个或两个以上的有序表组合成一个新的有序表。归并排序可分为多路归并排序,两路归并排序,既可用于内排序,也可以用于外排序。这里仅对内排序的两路归并排序进行讨论。
而我们这里所探究学习的二路归并排序,设计思路更加清晰、明了,程序本身也不像堆结构那样复杂,同时时间复杂度仅为0(N),同时在处理大规模归并排序的时候,排序速度也明显优于冒泡法等一些排序算法,提高排序算法的效率。
正文
2.1设计内容
设计一个利用二路归并算法实现的排序算法,针对输入的一组无序的数,利用栈或者数组机芯存储,然后进行数据的两两分组、比较,构造新的栈或者数组,依次类推,直到得到一个有序数组或者栈,最后输出有序数据,得到有序数据。
2.2设计要求
假设初始序列含有n 个数据(n是已经确定的数据个数),首先把n 个记录看成n
个长度为1的有序序列,进行两两归并,得到[n/2]个长度为2的有序序列,再两两归并直到所有记录归并成一个长度为n的有序序列为止。
2.3设计思想
对于任意一组数据,先利用栈或者数组将数据存储起来,其中,我们会用到线性表的顺序存储和链式存储两种存储方法。然后对存储的数据进行查找和筛选、排序,在出栈的过程中,同时对所取数据进行分组、排列,再次构造新的存储栈或者数组,依次类推,直到得到一个有序的数据时,执行出栈命令,输出最后的排序结果。
为了更清晰地说清楚这里的思想,大家来看图1,我们将本是无序的数组序列{16,7,13,10,9,15,3,2,5,8,12,1,11,4,6,14},通过两两合并排序后,再合并,最终获得了一个有序的数组。仔细观察它的形状,很像一棵倒置的完全二叉树,利用两两的比较,一次进行递归排序,最终得到一个从小到大的有序序列。
图 1
2.4 主要模块
主要模块式有四个阶段,依次是:输入一组无序的数列,用数据结构或者链式结构进行存储,然后进行查找、分组,进行最后的归并排序。(如图2所示)
图 2
2.5排序设计内容
此次操作要用到顺序结构的存储,顺序表的查找,以及二路归并排序。
2.5.1 顺序表的存储
首先利用顺序存储结构,把所有学生的成绩按每个班,每个学校,每个县,每个市,用线性表的顺序存储机构分别存储起来。
顺序表的基本操作如下:
Initlist(&L) 操作结果:构造一个空的线性表L; Destroylist(&L) 操作结果:销毁线性表L;
Clearlist((&lL) 操作结果:将L重置为空表(线性表L已经存在);
Iiselength(L) 操作结果:返回L中数据元素的个数;GetElem(L,I,&e) 操作结果:用e返回L中第i个数据元素的值;
2.5.2 顺序表的查找
Int Search-Sep(SSTable ST , KeyType key)
{//在顺序表ST中顺序查找其关键字等于Key的数据元素。若找到,则函数值为该元素在表中的位置,否则为0
ST.elem[0].Key=key; 哨兵;
For(i=ST.length; !EQ(ST.elem[i].key.key)) 从后往前找;
Return I; 找不到是i为0;
}
//Search-Sep
2.5.3 归并排序
代码:
/* 对顺序表L作归并排序 */
void MergeSort(SqList *L)
{
MSort(L->r,L->r,1,L->length);
}
2.6算法设计
本次设计主要用用到下面的算法:
2.6.1归并排序算法的实现
递归算法就是对n个数据进行两两归并,得到[n/2]个长度为2的有序序列,再两两归并直到所有记录归并成一个长度为n的有序序列为止。
递归算法实现中,最重要的就是对[n/2]进行很多次的归并递归排序算法的设计,调用函数MSort中采用了递归的算法思想,用较简短的语句,实现了多次递归排序。假设现在要对数组{50,10,90,30,70,40,80,60,20}进行排序,L.length=9,一下就是MSort 主要代码及实现过程。
/* 将SR[s..t]归并排序为TR1[s..t] */
1 void MSort(int SR[],int TR1[],int s, int t)
2 {
3int m;
4int TR2[MAXSIZE+1];
5if(s==t)
6TR1[s]=SR[s];
7Else
8{
9m=(s+t)/2; /* 将SR[s..t]平分为SR[s..m]和SR[m+1..t] */ 10MSort(SR,TR2,s,m); /* 递归地将SR[s..m]归并为有序的TR2[s..m] */
11MSort(SR,TR2,m+1,t); /* 递归地将SR[m+1..t]归并为有序TR2[m+1..t] */
12Merge(TR2,TR1,s,m,t); /* 将TR2[s..m]和TR2[m+1..t]归并到TR1[s..t] */
13}
14}
1) MSort被调用时,SR与TR1都是{50,10,90,30,70,40,80,60,20},s=1,t=9,最终我们的目的就是要将TR1中的数组排好顺序。
2) 第5行,显然s不等于t,执行第8~13行语句块。
3) 第9行,m=(1+9)/2=5。m就是序列的正中间下标
4) 此时第10行,调用“MSort(SR,TR2,1,5);”的目标就是将数组SR中的第1~5的关键字归并到有序的TR2(调用前TR2为空数组),第11行,调用“MSort(SR,TR2,6,9);”的目标就是将数组SR中的第6~9的关键字归并到有序的TR2。也就是说,在调用这两句代码之前,代码已经准备将数组分成两组。如图4所示:
图4
5) 第12行,函数Merge的代码细节一会再讲,调用“Merge(TR2,TR1,1,5,9);”的