版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、数据结构实验报告内部排序班级:13软工一班学号:13131113姓名:吕 蒙学号:13131116姓名:钱剑滨学号:13131142姓名:孔亚亚学号:13131144姓名:邱佃雨1613软工转本1钱剑滨实验报告内部排序实验报告信息工程 系13 软工转本1 日期2016年06月07日一、实验内容编写程序实现各种内部排序(包括:冒泡排序、插入排序、选择排序、希尔排序、 快速排序、堆排序、归并排序、基数排序),并运用这些排序对一组随机生成的数组进 行排序。二、时间复杂度1. 冒泡排序(O(n,)若文件的初始状态是正序的,一趟扫描即可完成排序。 所需的关键字比较次数 C和记录移动次数 M均达到最小值:
2、Cmin = n-1 , Mm如二0。所以,冒泡排序最好的时间复杂度为 0(«) 。若初始文件是反序的,需要进行五三趟排序。每趟排序要进行n- i次关键字的比较(1 <<1),且每次比较都必须移动记录三次来达到交换记录位置。在这种情况下,比较和移动次数均达到最大值:加小二业畀二0(段2瓜”。综上,因此冒泡Mmx = 3M2 11=°(层)冒泡排序的最坏时间复杂度为排序总的平均时间复杂度为0(n?) O2. 插入排序(O(nA2)如果目标是把n个元素的序列升序排列,那么采用插入排序存在最好情况和最坏情况。最好情况就是,序列已经是升序排列了,在这种情况下,需要进行的
3、比较操作需(n-1)次即可。最坏情况就是,序列是降序排列,那么此时需要进行的比较共有n(n-1)/2次。插入排序的赋值操作是比较操作的次数加上(n-1 )次。平均来说插入排序算法的时间复杂度为 0(门人2)。因而,插入排序不适合对于数据量比较大的排序应用。但是, 如果需要排序的数据量很小,例如,量级小于千,那么插入排序还是一个不错的选择。3. 选择排序(0付八2)选择排序的交换操作介于0和(n - 1)次之间。选择排序的比较操作为n (n - 1)/ 2次之间。选择排序的赋值操作介于0和3 (n - 1 )次之间。比较次数 0(门人2),比较次数与关键字的初始状态无关,总的比较次数N=(n-1
4、 ) +(n-2) +.+1=n*(n-1 ) /2。交换次数O(n),最好情况是,已经有序,交换 0次;最坏情况交换 n-1次,逆序交换 n/2次。交换次数比冒泡排序少多了,由于交换所需 CPU时间比比较所需的 CPU时间多,n值较小时,选择排序比冒泡排序快。4. 希尔排序希尔排序是按照不同步长对元素进行插入排序,当刚开始元素很无序的时候,步长最大,所以插入排序的元素个数很少,速度很快;当元素基本有序了,步长很小,插入排序对于有序的序列效率很高。所以,希尔排序的时间复杂度会比。何人2)好一些。5. 快速排序(O(M2)无论适用哪一种方法来选择pivot,由于我们不知道各个元素间的相对大小关系
5、(若知道就已经排好序了),所以我们无法确定pivot的选择对划分造成的影响。因此对各种pivot选择法而言,最坏情况和最好情况都是相同的。我们从直觉上可以判断出最坏情况发生在每次划分过程产生的两个区间分别包含 n-1个元素和1个元素的时候(设输入的表有n个元素)。下面我们暂时认为该猜测正确,在后文我们再详细证明该猜测。对于有n个元素的表Lp.r,由于函数Partition的计算时间为 0 (n),所以快速 排序在序坏情况下的复杂性有递归式如下:T(1)= 0 (1),T(n)=T(n -1)+T(1)+ 0 (n)(1)用迭代法可以解出上式的解为T(n)= 0 (n2)。这个最坏情况运行时间与
6、插入排序是一样的。下面我们来证明这种每次划分过程产生的两个区间分别包含n-1个元素和1个元素的情况就是最坏情况。设 T(n)是过程Quick_Sort作用于规模为n的输入上 的最坏情况的时间,则 T(n)=max(T(q)+T(n- q)+ 0 ( n),其中 1<q<-i1(2)我们假设对于任何k<n,总有T(k) < ck其中c为常数;显然当k=1时是成立的。将归纳假设代入 (2),得到:T(n) < max(cq2+c(n -q)2)+ 0 ( n)=c*max(q2+(n- q)2)+ 0 (n)因为在1,n-1上q2+(n-q)2关于q递减,所以当q=1
7、时q2+(n-q)2有最大值n2-2(n-1 )。于是有:T(n) Wcn22c(n-1)+ 0 (n) w cn2只要c足够大,上面的第二个 小于等于号就可以成立。于是对于所有的n都有T(n) <cn>这样,排序算法的最坏情况运行时间为0 (n2),且最坏情况发生在每次划分过程产生的两个区间分别包含n-1个元素和1个元素的时候。时间复杂度为 o (n2)。6. 堆排序(O(nlgn)堆排序过程的时间复杂度是O(nlgn)。因为建堆的时间复杂度是O(n)(调用一次);调整堆的时间复杂度是lgn,调用了 n-1次,所以堆排序的时间复杂度是O(nlgn)7. 归并排序(O(nlgn)时
8、间复杂度为O(nlogn)这是该算法中最好、最坏和平均的时间性能。空间复杂度为O(n)比较操作的次数介于(nlogn) / 2和nlogn - n + 1 。赋值操作的次数是(2nlogn)。归并算法的空间复杂度为:0 (n)归并排序比较占用内存,但却是一种效率高且稳定的算法。8. 基数排序(O(d(n+radix)时间效率:设待排序列为 n个记录,d个关键码,关键码的取值范围为 radix,则 进行链式基数排序白时间复杂度为 O(d(n+radix),其中,一趟分配时间复杂度为 O(n), 一趟收集时间复杂度为 O(radix),共进行d趟分配和收集。 空间效率:需要 2*radix 个指向
9、队列的辅助空间,以及用于静态链表的n个指针。三、算法稳定性1 .冒泡排序(稳定)冒泡排序就是把小的元素往前调或者把大的元素往后调。比较是相邻的两个元素比较,交换也发生在这两个元素之间。所以,如果两个元素相等,我想你是不会再无聊地把他们俩交换一下的;如果两个相等的元素没有相邻,那么即使通过前面的两两交换把 两个相邻起来,这时候也不会交换, 所以相同元素的前后顺序并没有改变,所以冒泡排序是一种稳定排序算法。2 .插入排序(稳定)插入排序是在一个已经有序的小序列的基础上,一次插入一个元素。 当然,刚开始这个有序的小序列只有 1个元素,就是第一个元素。比较是从有序序列的末尾开始, 也就是想要插入的元素
10、和已经有序的最大者开始比起,如果比它大则直接插入在其后 面,否则一直往前找直到找到它该插入的位置。如果碰见一个和插入元素相等的,那么插入元素把想插入的元素放在相等元素的后面。所以,相等元素的前后顺序没有改变, 从原无序序列出去的顺序就是排好序后的顺序,所以插入排序是稳定的。3 .选择排序(不稳定)选择排序是给每个位置选择当前元素最小的,比如给第一个位置选择最小的, 在剩余元素里面给第二个元素选择第二小的,依次类推,直到第n-1个元素,第n个元素不用选择了,因为只剩下它一个最大的元素了。那么,在一趟选择,如果一个元素比当前元素小,而该小的元素又出现在一个和当前元素相等的元素后面,那么交换后稳定性
11、就被破坏了。比较拗口,举个例子,序列 5 8 5 2 9,我们知道第一遍选择第 1个元素5 会和2交换,那么原序列中两个 5的相对前后顺序就被破坏了,所以选择排序是一个 不稳定的排序算法。4 .希尔排序(不稳定)由于多次插入排序,我们知道一次插入排序是稳定的,不会改变相同元素的相对顺序,但在不同的插入排序过程中, 相同的元素可能在各自的插入排序中移动,最后其稳定性就会被打乱,所以 shell排序是不稳定的。5 .快速排序(不稳定)快速排序有两个方向,左边的i下标一直往右走,当 ai <= acenter_index,其中center_index是中枢元素的数组下标,一般取为数组第0个元素
12、。而右边的j下标一直往左走,当aj > acenter_index。如果i和j都走不动了,i <= j,交换ai和aj,重复上面的过程,直到i>j。交换aj和acenter_index,完成一趟快速排序。在中枢元素和 aj交换的时候,很有可能把前面的元素的稳定性打乱,比如序列5 3 3 4 3 8 9 10 11 ,现在中枢元素5和3(第5个元素,下标从1开始计)交换就会把元素3的稳定性打乱, 所以快速排序是一个不稳定的排序算法,不稳定发生在中枢元素和aj交换的时刻。6 .堆排序(不稳定)堆排序的时间,主要由建立初始堆和反复重建堆这两部分的时间开销构成,它们均是通过调用Hea
13、pify实现的。堆排序的最坏时间复杂度为O(nlgn)。堆排序的平均性能较接近于最坏性能。由于建初始堆所需的比较次数较多,所以堆排序不适宜于记录数较少的文件。堆排序是就地排序,辅助空间为0(1),它是不稳定的排序方法。7 .归并排序(稳定)归并排序是一种稳定的排序8 .基数排序(稳定)基数排序是一种稳定的排序四、各排序介绍和算法实现1 .冒泡排序冒泡排序算法的运作如下:(从后往前)(1)比较相邻的元素。如果第一个比第二个大,就交换他们两个。(2)对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。在这一点, 最后的元素应该会是最大的数。(3)针对所有的元素重复以上的步骤,除了最后一个。
14、(4)持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。 代码:void maopao(int numberNMAX)int temp, i, j, t;yuan(numberN);int numberYMAX;for(t = 0; t < N; t+) numberYt = numberNt;for(i = 0; i < N - 1; i+)for(j = 0; j < N - (i + 1); j+) if(numberYj > numberYj + 1) temp = numberYj;numberYj = numberYj + 1;numbe
15、rYj + 1 = temp;sheng(numberY);2 .插入排序一般来说,插入排序都采用 in-place在数组上实现。具体算法描述如下:(1)从第一个元素开始,该元素可以认为已经被排序(2)取出下一个元素,在已经排序的元素序列中从后向前扫描(3)如果该元素(已排序)大于新元素,将该元素移到下一位置(4)重复步骤3,直到找到已排序的元素小于或者等于新元素的位置(5)将新元素插入到下一位置中(6)重复步骤25代码:void charu(int numberNMAX)int i,j,t;int temp;int numberYMAX;yuan(numberN);for(t = 0; t
16、< N; t+)numberYt = numberNt;for(i=1;i<N;i+)temp=numberYi;for(j=i;j>0&&numberYj-1>temp;j-)numberYj=numberYj-1;numberYj=temp;sheng(numberY);3 .选择排序对比数组中前一个元素跟后一个元素的大小,如果后面的元素比前面的元素小则用一个变量k来记住他的位置,接着第二次比较,前面后一个元素现变成了 前一个元素”,继续跟他的 后一个元素”进行比较如果后面的元素比他要小则用变量k记住它在数组中的位置(下标),等到循环结束的时候,我们
17、应该找到了最小的那个数的下标了,然 后进行判断,如果这个元素的下标不是第一个元素的下标,就让第一个元素跟他交换一下值,这样就找到整个数组中最小的数了。然后找到数组中第二小的数,让他跟数组中第二个元素交换一下值,以此类推。代码:void xuanze(int numberNMAX) int temp, i, j, t, min;int numberYMAX; yuan(numberN);for(t = 0; t < N; t+) numberYt = numberNt;for(i = 0; i < N - 1; i+) min = i;for(j = i + 1; j < N;
18、 j+) if(numberYmin > numberYj) min = j; temp = numberYi;numberYi = numberYmin; numberYmin = temp;sheng(numberY);4 .希尔排序先取一个小于n的整数di作为第一个增量,把文彳的全部记录分成di个组。所有距离为di的倍数的记录放在同一个组中。先在各组内进行直接插入排序;然后,取 第二个增量d2Vdi重复上述的分组和排序,直至所取的增量dt=1(dt<dt- l< <d2<d1),即所有记录放在同一组中进行直接插入排序为止。代码:void xier(int n
19、umberNMAX) int d, i, j, t, temp;int numberYMAX;yuan(numberN);for(t = 0; t < N; t+) numberYt = numberNt;for(d = N/2;d >= i;d = d/2)for(i = d; i < N;i+)temp = numberYi;for(j = i - d;(j >= 0) && (numberYj > temp);j = j-d) numberYj + d = numberYj; | numberYj + d = temp;sheng(numbe
20、rY);5 .快速排序设要排序的数组是 A0AN-1,首先任意选取一个数据(通常选用数组的第一个数)作为关键数据,然后将所有比它小的数都放到它前面,所有比它大的数都放到它后面,这个过程称为一趟快速排序。值得注意的是,快速排序不是一种稳定的排序算法, 也就是说,多个相同的值的相对位置也许会在算法结束时产生变动。一趟快速排序的算法是:(1)设置两个变量i、j,排序开始的时候:i=0 , j=N-1 ;(2)以第一个数组元素作为关键数据,赋值给 key,即key=A0;(3)从j开始向前搜索,即由后开始向前搜索(j-),找到第一个小于key的值Aj,将Aj和Ai互换;(4)从i开始向后搜索,即由前开
21、始向后搜索(i+),找到第一个大于 key的Ai,将Ai和Aj互换;(5)重复第3、4步,直到i=j; (3,4步中,没找到符合条件的值,即 3中Aj不小于 key,4中Ai不大于key的时候改变j、i的值,使得j=j-1 , i=i+1 ,直至找到为止。 找到符合条件的值,进行交换的时候i, j指针位置不变。另外,i=j这一过程一定正文?是i+或j-完成的时候,此时令循环结束)。代码:int partions(int numberYMAX,int low,int high)int prvotkey=numberYlow;while (low<high)while (low<hig
22、h&&numberYhigh>=prvotkey)-high;numberYlow=numberYhigh;while (low<high&&numberYlow<=prvotkey) +low;numberYhigh=numberYlow; numberYlow=prvotkey;return low;void quicksort(int numberYMAX,int low,int high) int prvotloc;if(low<high) prvotloc=partions(numberY,low,high);/ 将第一次排序的
23、结果作为枢轴quicksort(numberY,low,prvotloc-1);/递归调用排序由 low 至1J prvotloc-1quicksort(numberY,prvotloc+1,high);/递归调用排序由 prvotloc+1 至U highvoid kuaisu(int numberNMAX)int i;int numberYMAX;yuan(numberN);for(i = 0; i < N; i+)numberYi = numberNi;quicksort(numberY, 0, N-1); sheng(numberY);6.堆排序大根堆排序算法的基本操作:(1)建
24、堆,建堆是不断调整堆的过程,从 len/2处开始调整,一直到第一个节点,此处len是堆中元素的个数。建堆的过程是线性的过程,从 len/2到0处一直调用调整堆 的过程,相当于o(h1)+o(h2)+o(hlen/2) 其中h表示节点的深度,len/2表示节点的个 数,这是一个求和的过程,结果是线性的O(n)。(2)调整堆:调整堆在构建堆的过程中会用到,而且在堆排序过程中也会用到。利用的思想是比较节点i和它的孩子节点left(i),right(i),选出三者最大(或者最小)者,如果最 大(小)值不是节点i而是它的一个孩子节点,那边交互节点i和该节点,然后再调用调整堆过程,这是一个递归的过程。 调
25、整堆的过程时间复杂度与堆的深度有关系,是lgn的操作,因为是沿着深度方向进行调整的。(3)堆排序:堆排序是利用上面的两个过程来进行的。首先是根据元素构建堆。然后将堆的根节点取出(一般是与最后一个节点进行交换),将前面len-1个节点继续进行堆调整的过程,然后再将根节点取出,这样一直到所有节点都取出。代码:/ array是待调整的堆数组, 本函数功能是:根据数组 代码:/ array是待调整的堆数组, 本函数功能是:根据数组 代码:i是待调整的数组元素的位置, array构建大根堆nlength是数组的长度i是待调整的数组元素的位置,nlength是数组的长度array构建大根堆void Hea
26、pAdjust(int array口,int i, int nLength) int nChild;int nTemp;for (nTemp = arrayi; 2 * i + 1 < nLength; i = nChild) /子结点的位置=2* (父结点位置)+ 1nChild = 2 * i + 1;/得到子结点中较大的结点if ( nChild < nLength-1 && arraynChild + 1 > arraynChild) +nChild;/如果较大的子结点大于父结点那么把较大的子结点往上移动,替换它的父 结点if (nTemp <
27、arraynChild)arrayi = arraynChild;arraynChild= nTemp; else/否则退出循环break;/堆排序算法void dui(int numberNMAX)int tmp, t, i;int numberYMAX;yuan(numberN);for(t = 0; t < N; t+) numberYt = numberNt;/调整序列的前半部分元素,调整完之后第一个元素是序列的最大的元素/length/2-1是第一个非叶节点,此处"/"为整除for (i = floor(N -1)/ 2 ; i >= 0; -i) H
28、eapAdjust(numberY, i, N);/从最后一个元素开始对序列进行调整,不断的缩小调整的范围直到第一个元素for (i = N - 1; i > 0; -i)/把第一个元素和当前的最后一个元素交换,/保证当前的最后一个位置的元素都是在现在的这个序列之中最大的/ Swap(&array0, &arrayi);tmp = numberYi;numberYi = numberY0;numberY0 = tmp;/不断缩小调整heap的范围,每一次调整完毕保证第一个元素是当前序列的 最大值HeapAdjust(numberY, 0, i); sheng(number
29、Y);7.归并排序归并操作的工作原理如下:(1)申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列(2)设定两个指针,最初位置分别为两个已经排序序列的起始位置(3)比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到 下一位置(4)重复步骤(3)直到某一指针超出序列尾(5)将另一序列剩下的所有元素直接复制到合并序列尾代码:归并操作void Merge(int sourceArr, int targetArr, int startindex, int midIndex, int endindex)int i, j, k;for(i = midindex+1,
30、j = startindex; startindex <= midIndex && i <= endindex; j+) if(sourceArrstartindex < sourceArri)targetArrj = sourceArrstartindex+; else targetArrj = sourceArri+;if(startindex <= midindex)for(k = 0; k <= midindex-startindex; k+)targetArrj+k = sourceArrstartindex+k;if(i <= e
31、ndindex)for(k = 0; k <= endindex- i; k+) targetArrj+k = sourceArri+k;内部使用递归,空间复杂度为n+lognvoid MergeSort(int sourceArr口,int targetArr口,int startindex, int endindex)int midIndex;int tempArrMAX; 此处大小依需求更改 if(startIndex = endindex)targetArrstartIndex = sourceArrstartIndex;elsemidIndex = (startindex + endIndex)/2;MergeSort(sourceArr, tempArr, startindex, midIndex);Me
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2《我们的班规我们订》 第二课时 说课稿-2024-2025学年道德与法治四年级上册统编版
- 4 我爱学语文(说课稿)-2024-2025学年统编版语文一年级上册
- 2024植物墙合同模板
- 福建省南平市文昌学校2021年高三英语期末试卷含解析
- 福建省南平市外屯中学2021年高三物理联考试卷含解析
- 专项研发借款协议(2024版)版B版
- 硕士研究之路
- 农业发展的新里程
- 绿色使命:企业的环保行动
- 复试保密协议书(2篇)
- 新疆塔城地区(2024年-2025年小学六年级语文)部编版期末考试(下学期)试卷及答案
- 四人合伙投资协议书范本
- 2024年9月时事政治试题带答案
- 反射疗法师3级考试题库(含答案)
- 汽车供应商审核培训
- 《计算机网络 》课件第1章
- 山东省济南市2023-2024学年高二上学期期末考试地理试题 附答案
- 期末复习试题1(试题)-2024-2025学年二年级上册数学北师大版
- 1《地球的表面》说课稿-2024-2025学年科学五年级上册教科版
- 汽车以租代购合同完整版完整版
- 音乐制作基础知识单选题100道及答案解析
评论
0/150
提交评论