6、分割成若干长度为m的子序列,分别对各子表进行直接插入排序。仅增量因子为1时,整个序列作为一个表来处理,表长度即为整个序列的长度。希尔排序的示例:初始关躍字n4938659776132749550449|13t-38L2765L49975576u04j一趟排序结果:i1327455044938659776r13r762|0465|49,7|二趙排序结果;13044938274955059776三趙排序结果:04132738-J4$4955657697算法实现:我们简单处理增量序列:增量序列d=n/2,n/4,n/81n为要排序数的个数..
7、6.37.38.即:先将要排序的一组记录按某个增量d(n/2,n为要排序数的个数)分成若干组子序列,每组中记录的下标相差d.对每组中全部元素进行直接插入排序,然后再用一个较小的增量(d/2)对它进行分组,在每组中再进行直接插入排序。继续不断缩小增量直至为1,最后使用直接插入排序完成排序。voidprint(inta,intn,inti)coutvvi<<":"for(intj
8、=0;j<8;j+)cout<9、intdk)/若第i个元素大于i-1元素,直接插入。/复制为哨兵,即存储待排序元素/首先后移一个元素/查找在有序表的插入位置/元素后移/插入到正确位置/*先按增量d(n/2,n为要排序数的个数进行希尔排序*/39.intdk=n/2;40.while(dk>=1)41.ShelllnsertSort(a,n,dk);42.dk=dk/2;43.44.45.intmain()46.inta8=3,1,5,7,2,4,9,6;47./ShellInsertSort(a,8,1);/直接插入排序48.shellSort(a,8);/希尔插入排序49.pri
10、nt(a,8,8);50.希尔排序时效分析很难,关键码的比较次数与记录移动次数依赖于增量因子序列d的选取,特定情况下可以准确估算出关键码的比较次数和记录的移动次数。目前还没有人给出选取最好的增量因子序列的方法。增量因子序列可以有各种取法,有取奇数的,也有取质数的,但需要注意:增量因子中除1外没有公因子,且最后一个增量因子必须为1。希尔排序方法是一个不稳定的排序方法。3.选择排序一简单选择排序(SimpleSelectionSort)基本思想:在要排序的一组数中,选出最小(或者最大)的一个数与第i个位置的数交换;然后在剩下的数当中再找最小(或者最大)的与第2个位置的数交换,依次类推,直
13、<<""coutvvendl;/*数组的最小值*returnint数组的键值*/intSelectMinKey(inta,intn,inti)intk=i;for(intj=i+1;jaj)k=j;..6./**选择排序*/voidselectSort(inta,intn)intkey,tmp
14、;for(inti=0;i15、,8,8);简单选择排序的改进二元选择排序简单选择排序,每趟循环只能确定一个元素排序后的定位。我们可以考虑改进为每趟循环确定两个元素(当前趟最大和最小记录)的位置,从而减少排序所需的循环次数。改进后对n个数据进行排序,最多只需进行n/2趟循环即可。具体实现如下:voidSelectSort(intr,intn)inti,j,min,max,tmp;for(i=1;i<=n/2;i+)/做不超过n/2趟选择排序min=i;max=i;/分别记录最大和最小关键字记录位置for(j=i+1;j<=n-i;j+)7.if(r
16、j>rmax)7.18.19.max=j;continueif(rj17、为最小项(小顶堆)(或不若以一维数组存储一个堆,则堆对应一棵完全二叉树,且所有非叶结点的值均不大于小于)其子女的值,根结点(堆顶元素)的值是最小(或最大)的。如:(a)大顶堆序列:(96,83,27,38,11,09)(b)小顶堆序列:(12,36,24,85,47,30,53,91)初始时把要排序的n个数的序列看作是一棵顺序存储的二叉树(一维数组存储二叉树),调整它们的存储序,使之成为一个堆,将堆顶元素输出,得到n个元素中最小(或最大)的元素,这时堆的根节点的数最小(或者最大)。然后对前面(n-1)个元素重新调整使之成为堆,输出堆顶元素,得到n个元素中次小(或次大)的元素。依此
18、类推,直到只有两个节点的堆,并对它们作交换,最后得到有n个节点的有序序列。称这个过程为堆排序。因此,实现堆排序需解决两个问题:1.如何将n个待排序的数建成堆;2.输出堆顶元素后,怎样调整剩余n-1个元素,使其成为一个新堆。首先讨论第二个问题:输出堆顶元素后,对剩余n-1元素重新建成堆的调整过程。调整小顶堆的方法:1)设有m个元素的堆,输出堆顶元素后,剩下m-1个元素。将堆底元素送入堆顶(最后一个元素与堆顶进行交换),堆被破坏,其原因仅是根结点不满足堆的性质。2)将根结点与左、右子树中较小元素的进行交换。3)若与左子树交换:如果左子树堆被破坏,即左子树的根结点不满足堆的性质,则重复
21、立堆,二是堆顶与堆的最后一个元素交换位置。所以堆排序有两个函数组成。一是建堆的渗透函数,二是反复调用渗透函数实现排序的函数。voidprint(inta,intn)for(intj=0;j22、s,intlength)inttmp=Hs;intchild=2*s+1;/左孩子结点的位置。(i+1为当前调整结点的右孩子结点的位置)while(child23、替换它的父结点重新设置s,即待调整的下一个结点的位置如果当前待调整结点大于它的左右孩子,则不需要调/当前待调整的结点放到比其大的孩子结点位置上5.76.77.*初始堆进行调整*将H0.length-1建成堆*调整完之后第一个元素是序列的最小的元素*/voidBuildingHeap(intH,intlength)/最后一个有孩子的节点的位置i
24、=(length-1)/2for(inti=(length-1)/2;i>=0;-i)HeapAdjust(H,i,length);/*堆排序算法*/voidHeapSort(intH,intlength)/初始堆BuildingHeap(H,length);/从最后一个元素开始对序列进行调整for(inti=length-1;i>0;-i)/交换堆顶元素H0和堆中最后一个元素inttemp=Hi;Hi=H0;H0=temp;/每次交换堆顶元素和堆中最后一个元素之后,都要对堆进行调整HeapAdj
27、)2.for(inti=0;iaj+1)5.6.inttmp=aj;aj=aj+1;aj+1=tmp;0.冒泡排序算法的改进对冒泡排序常见的改进方法是加入一标志性变量exchange,用于标志某一趟排序过程中是否有数据交换,如果进行某一趟排序时并没有进行数据交换,则说明数据已经按要求排列好,可立即结束排序,避免不必要的比较过程。本文再提供以下两种改进算法:1设置一标志性变量pos,用于记录每趟排序中最后一次进行交换的
28、位置。由于pos位置之后的记录均已交换到位,故在进行下一趟排序时只要扫描到pos位置即可。改进后算法如下:1.voidBubble_1(intr,intn)2.inti=n1;/初始时,最后位置保持不变3.while(i>0)4.intpos=0;/每趟开始时,无记录交换5.for(intj=0;jrj+1)7.pos=j;/记录交换的位置8.inttmp=rj;rj=rj+1;rj+1=tmp;9.10.i=pos;/为下一趟排序作准备11.12.2传统冒泡排序中每一趟排序操作只能找到一个最大值或
29、最小值,我们考虑利用在每趟排序中进行正向和反向两遍冒泡的方法一次可以得到两个最终值(最大者和最小者),从而使排序趟数几乎减少了一半。改进后的算法实现为:1.voidBubble_2(intr,intn)2.intlow=0;3.inthigh=n-1;/设置变量的初始值4.inttmp,j;5.while(lowrj+1)tmp=rj;rj=rj+1;rj+1=tmp;-high;for(j=high;j&
30、gt;low;-j)if(rj31、:(a)趟排序的过程:初始戋犍字pivotkey491IISB659761327J,1j进行1次交换之后27386S4977613Jf.IJ49进行2扰交换之后27385776)34165A+5进行3次交换之后2738u97766549.f4斗i1i1|j逬行4次交换之后273837697t6549j*J完成一超排序2738134976976549(a)(b)排序的全过程初蜡状蛊4938659776132749一次划分之后(27384976976549分别进行快速排序132738结康结東4965769749(65)赭東结束有洋序列1327334949657697(b)算法的实现:
32、递归实现:1.voidprint(inta,intn)2.for(intj=0;j33、e(low=privotKey)-high;high所指位置向前搜索,至多到low+1位置。将比基准元素小的交换到低端20.swap(&alow,&ahigh);21.while(low34、high)30.if(low35、a,10);II基准元素/从表的两端交II从II将表一分为二II递归对低子表递归排II递归对高子表递归排..2.分析:快速排序是通常被认为在同数量级(0(nIog2n)的排序方法中平均性能最好的。但若初始序列按关键码有序或基本有序时,快排序反而蜕化为冒泡排序。为改进之,通常以三者取中法”来选取基准记录,即将排序区间的两个端点与中点三个记录关键码居中的调整为支点记录。快速排序是一个不稳定的排序方法。快速排序的改进在本改进算法中,只对长度大于k的子序列递归调用快速排序,让原序列基
37、(low=privotKey)-high;/从high所指位置向前搜索,至多到Iow+1位置。将比基准元素小的交换到低端swap(&alow,&ahigh);while(low38、ntlow,inthigh,intk)if(high-low>k)/长度大于k时递归,k为指定的数算法保持intpivot=partition(r,low,high);/调用的Partition不变qsort_improve(r,low,pivot-1,k);qsort_improve(r,pivot+1,high,k);voidquickSort(intr,intn,intk)qsort_improve(r,0,n,k);/先调用改进算法Qsort使之基本有序/再用插入排序对基本有序序列排序for(inti=1
39、;i<=n;i+)inttmp=ri;intj=i-1;while(tmp41、辅助数组的起始下标2.若i>m或j>n,转其中一个子表已合并完,比较选取结束3.选取ri和rj较小的存入辅助数组rf如果ri42、for(j=m+1,k=i;i<=m&&j<=n;+k)...5.if(rj43、后一个子表长度可能为1夕卜,其余子表长度均为2。再进行两两合并,直到生成n个元素按关键码有序的表。voidprint(inta,intn)for(intj=0;j44、=rj+;elserfk=ri+;while(i<=m)rfk+=ri+;while(j<=n)rfk+=rj+;print(rf,n+1);voidMergeSort(ElemType*r,ElemType*rf,intlenght)intlen=1;ElemType*q=r;ElemType*tmp;26.while(len45、rf,i,i+s-1,i+len-1);/对等长的两个子表合并32.i=i+len;33.34.if(i+s