1、南京邮电大学计算机学院 陈慧南 2006年9月,数据结构,Data Structures in C+,南京邮电大学计算机学院 陈慧南 2006年9月,第10章 内排序,南京邮电大学计算机学院 陈慧南 2006年9月,10.1 基本概念 10.2 简单排序算法 10.3 快速排序 10.4 两路合并排序,南京邮电大学计算机学院 陈慧南 2006年9月,10.1 基本概念,南京邮电大学计算机学院 陈慧南 2006年9月,设有n个数据元素的序列(R0,R1,Rn-1),Ki是Ri的关键字。所谓排序,就是找(0,1, ,n-1)的一种排列p(0),p(1), ,p(n-1),使得序列按K p(0)Kp
2、(1)Kp(n-1) (非递减)或K p(0)Kp(1)Kp(n-1) (非递增)次序排列为:( Rp(0),Rp(1),Rp(n-1),南京邮电大学计算机学院 陈慧南 2006年9月,序列中两个元素Ri和Rj (ij),且Ki=Kj,若排序后仍保持p(i)p(j),即Ri 仍然排在Rj之前,则称所用的排序算法是稳定的。反之,称该排序算法是不稳定的。 如果待排序元素总数相对于内存而言较小,整个排序过程可以在内存中进行,则称之为内部排序;反之,如果待排序元素总数较多,不能全部放入内存,排序过程中需访问外存,则称之为外部排序。本章讨论内部排序。,南京邮电大学计算机学院 陈慧南 2006年9月,10
3、.2 简单排序算法,南京邮电大学计算机学院 陈慧南 2006年9月,10.2.1 简单选择排序,南京邮电大学计算机学院 陈慧南 2006年9月,template void SelectSort(T A, int n) int small;for (int i=0; in-1; i+) small=i; for (int j=i+1;jn;j+) if (AjAsmall) small=j; Swap(Ai,Asmall); ,南京邮电大学计算机学院 陈慧南 2006年9月,该算法执行时间与元素的初始排列无关。不论初始排列如何,该算法都必须执行n-1趟,每趟执行n-i-1次关键字的比较,这样总的
4、比较次数为:,南京邮电大学计算机学院 陈慧南 2006年9月,简单选择排序的最好、最坏和平均情况的时间复杂度都为O(n2),而且。另外,它还需交换元素(n-1)次和移动元素3(n-1)次(交换一次要移动三个元素)。该排序算法经过一趟排序后,就能确定一个元素的最终位置。 简单选择排序是不稳定的排序方法,南京邮电大学计算机学院 陈慧南 2006年9月,10.2.2 直接插入排序,南京邮电大学计算机学院 陈慧南 2006年9月,template void InsertSort(T A, int n) for(int i=1; i0 ,南京邮电大学计算机学院 陈慧南 2006年9月,直接插入排序算法必
5、须进行n-1趟。最好情况下,即初始序列有序,执行n-1趟,但每一趟只比较一次,移动元素两次,总的比较次数是(n-1),移动元素次数是2(n-1)。因此最好情况下的时间复杂度就是O(n)。最坏情况(非递增)下,最多比较i次, 因此需要的比较次数是:,南京邮电大学计算机学院 陈慧南 2006年9月,9.2.3 冒泡排序,(48,36,68,72,12,48,02) (36,48,68,72,12,48,02) (36,48,68,72,12,48,02) (36,48,68,72,12,48,02) (36,48,68,12,72,48,02) (36,48,68,12,48,72,02) (36
6、,48,68,12,48,02,72),南京邮电大学计算机学院 陈慧南 2006年9月,南京邮电大学计算机学院 陈慧南 2006年9月,template void BubbleSort(T A, int n) int i,j,last;i=n-1; while (i0) last=0; for (j=0; ji; j+) if (Aj+1Aj) Swap(Aj,Aj+1); last=j; i=last; ,南京邮电大学计算机学院 陈慧南 2006年9月,当原始数据正向有序时,冒泡排序出现最好情况。此时,只需进行一趟排序,作n-1次关键字比较,因此最好情况下的时间复杂度是O(n)。当原始数据反
7、向有序时,冒泡排序出现最坏情况。此时,需进行n-1趟排序,第i趟需作(n-i)次关键字间的比较,并且需执行(n-i)次元素交换,所以,比较次数为,移动元素次数为因此,最坏情况下的时间复杂度为O(n2)。,南京邮电大学计算机学院 陈慧南 2006年9月,10.3 快速排序,南京邮电大学计算机学院 陈慧南 2006年9月,快速排序的基本思想对任意给定的序列中某个元素,经过一趟排序后,将原序列分割成两个子序列(Rp(0),Rp(1),Rp(s-1)和(Rp(s+1),Rp(s+2),Rp(n-1),其中前一个子序列中的所有元素的关键字均小于或等于该元素的关键字值Kp(s),后一个子序列中元素的关键字
8、均大于或等于Kp(s)。 称该元素Rp(s)为分割元素,子序列(Rp(0),Rp(1),Rp(s-1)为其低端序列,(Rp(0),Rp(1),Rp(s-1)为其高端序列。很明显,以后只需对低端和高端序列分别进行快速排序,直到子序列为空或只有一个元素时结束,最后得到有序序列。,南京邮电大学计算机学院 陈慧南 2006年9月,template void QSort(T A, int left, int right) int i,j;if (leftAleft); if (ij) Swap(Ai,Aj); while (ij); Swap(Aleft,Aj); QSort(A,left,j-1);
9、QSort(A,j+1,right); ,南京邮电大学计算机学院 陈慧南 2006年9月,template void QuickSort(T A, int n) QSort(A,0,n-1); ,南京邮电大学计算机学院 陈慧南 2006年9月,快速排序示例,(48,36,68,72,12,48,02) (12,36,02,48)48(72,68),南京邮电大学计算机学院 陈慧南 2006年9月,南京邮电大学计算机学院 陈慧南 2006年9月,从上述快速排序算法中可以看出,如果每一次分划操作后,左、右两个子序列的长度基本相等,则快速排序的效率最高,其最好情况时间复杂度为O(nlog2n);反之,
10、如果每次分划操作所产生的两个子序列,其中之一为空序列,此时,快速排序效率最低,其最坏情况时间复杂度为O(n2)。如果选择左边第一个元素为主元,则快速排序的最坏情况发生在原始序列正向有序或反向有序时。快速排序的平均情况时间复杂度为O(nlog2n)。,南京邮电大学计算机学院 陈慧南 2006年9月,系统需要有一个堆栈来实现快速排序递归算法。在最坏情况下,程序126所需的系统栈的最大深度为O(n)。为了减少栈空间大小,可在每次分划后,将较大子序列的上、下界进栈,而对较小的子序列先进行排序。这样可使所需的栈空间大小降为O(log2n)。,南京邮电大学计算机学院 陈慧南 2006年9月,10.4 两路
11、合并排序,南京邮电大学计算机学院 陈慧南 2006年9月,南京邮电大学计算机学院 陈慧南 2006年9月,template void Merge(T A,int i1,int j1,int i2,int j2) T *Temp=new Tj2-i1+1; int i=i1,j=i2,k=0; while (i=j1 ,南京邮电大学计算机学院 陈慧南 2006年9月,template void MergeSort(T A, int n) int i1,j1,i2,j2; int size=1; while (sizen-1) j2=n-1; else j2=i2+size-1; Merge(A,
12、i1,j1,i2,j2); i1=j2+1; size*=2; ,南京邮电大学计算机学院 陈慧南 2006年9月,该算法中size的取值不超过log2n个,即最多进行log2n趟排序,每趟都要扫描n个元素,因此两路合并排序的时间复杂度是O(nlog2n)。 但是它必须借助一个与原序列等大小的辅助数组方能实现,故其附加存储辅助空间为O(n)。该算法经过一趟排序后,不能确定任意一个元素的最终位置,它的执行时间与元素的初始排列无关。两路合并排序是一种稳定的排序方法。,南京邮电大学计算机学院 陈慧南 2006年9月,排序算法 最好情况 平均情况 最坏情况 简单选择排序 O(n2) O(n2) O(n2) 直接插入排序 O(n) O(n2) O(n2) 冒泡排序 O(n) O(n2) O(n2) 快速排序 O(nlog2n) O(nlog2n) O(n2) 两路合并排序 O(nlog2n) O(nlog2n) O(nlog2n),