排序:
(1)内部排序与外部排序
内部排序:指待排序记录全部存放在计算机内存中进行排序的过程
外部排序:指的是待排序记录的数量很大,以致内存一次不能容纳全部记录,在排序过程中尚需对外存进行访问的排序过程。
(2)内部排序方法的分类
1、插入类:如交换插入排序、折半插入排序和希尔排序
2、交换类:主要包括冒泡排序和快速排序
3、选择类:主要包括简单选择排序、树形选择排序和堆排序
4、归并类:通过“归并”两个或两个以上的记录有序子序列,足部增加记录有序序列的长度。2-路归并排序是最为常见的归并排序方法
5、分配类:是唯一一类不需要进行关键字之间比较的排序方法,排序时主要利用分配和收集两种基本操作来完成。基数排序是主要的分配类排序方法。
(3)排序的稳定性
当排序记录中的关键字有相同时,返回的结果唯一。
(4)排序算法效率的评价指标
1、执行时间
2、辅助空间
插入排序:
(一)直接插入排序:
时间复杂度:
最大比较次数KCN=(n+2)(n-1)/2≈n^2/2
最大记录移动次数RMN=(n+4)(n-1)/2≈n**2/2
若排序序列中出现各种可能排序的概率相同,则取上诉最好情况和最坏情况的均值,约为n^2/4
(二)折半插入排序
void BInsertSort(SqList &L) {//对顺序表L做折半插入排序 for(i=2; i<L.length; i++) { L.r[0]=L.r[i]; //将待插入的记录暂存到监视哨中 low=1; high=i-1; //置查找区间初值 while(low<=high) //在r[low.high] 中折半插入的位置 { m=(low+high)/2; if(L.r[0].key<L.r[m].key) high = m-1;//插入点在前一子表 else low=m+1;//插入点在后一子表 } for(j=1; j>=high+1; j--) L.r[j+1]=L.r[j];//记录后移 L.r[righ+1]=L.r[0]; //将r[0]即原r[i],插入到正确位置 } }
时间复杂度:O(n^2)
空间复杂度:O(1) //需要一个记录的辅助空间r[0]
算法特显:1、稳定排序 2、因为要进行折半查找,所以只能用于顺序结构,不能用于链式结构 3、适和初始记录无序,n较大时的情况
(三)希尔排序(又称缩小增量排序)
具体算法:书P240
时间复杂度:一大难题
空间复杂度O(1)
交换排序:
(四)冒泡排序
时间复杂度:O(n^2)
空间复杂度:O(1)
(五)快速排序
书P243
时间复杂度:O(nlog2 n)
空间复杂度:最好为O(log2 n) 最坏O(n)
选择排序:
(六)简单选择排序
1 void selectSort(int[] a, int len) { 2 for (int i = 0; i < len - 1; i++) { 3 int min = i; 4 for (int j = i + 1; j < len; j++) { 5 if (a[min] > a[j]) { 6 min = j; 7 } 8 } 9 if (min != i) { 10 int temp = a[min]; 11 a[min] = a[i]; 12 a[i] = temp; 13 } 14 } 15 }
(七)树形选择排序
(八)堆排序
归并排序:
算法思想: 假设初始序列含有 n 个记录,首先将这 n 个记录看成 n 个有序的子序列, 每个子序列的长度为 1,然后两两归并,得到[2/n]个长度为 2(n 为奇数时,最后一个序列的长度为 1)的有序子序列。在此基础上,再对长度为2的有序子序列进行两两归并,得到若干个长度为4的有 序子序列。如此重复,直至得到一个长度为 n的有序序列为止。
(九)2-路归并
基数排序:
(十)多关键字的排序
(十一)链式基数排序
外部排序:
置换-选择排序: