第八章:排序
一、排序的基本概念
排序(Sort) ,就是重新排列表中的元素,使表中的元素满⾜按关键字有序的过程。
排序算法的评价指标
算法的稳定性。
若待排序表中有两个元素Ri和Rj,其对应的关键字相同即keyi = keyj,且在排序前Ri在Rj的前⾯,若使⽤某⼀排序算法排序后, Ri仍然在Rj的前⾯,则称这个排序算法是稳定的,否则称排序算法是不稳定的。
排序算法的分类
- 内部排序——数据都在内存中
关注如何使算法时间、空间复杂度更低
- 外部排序——数据太多,无法全部放入内存
还要关注如何使读/写磁盘次数更少
二、插入排序
1.算法思想
每次将⼀个待排序的记录按其关键字⼤⼩插⼊到前⾯已排好序的⼦序列中,直到全部记录插⼊完成。
2.算法实现
//不带“哨兵”
void InsertSort(int A[], int n){
//A中共n个数据元素
int i,j,temp;
for(i=1; i<n; i++)
if(A[i]<A[i-1]){
//A[i]关键字小于前驱
temp = A[i];
for(j=i-1; j>=0 && A[j]>temp; --j)
A[j+1] = A[j]; //所有大于temp的元素都向后挪
A[j+1] = temp; //复制到插入位置
}
}
//带“哨兵”
void InsertSort(int A[], int n){
//A中从1开始存储,0放哨兵
int i,j;
for(i=2; i<n; i++)
if(A[i]<A[i-1]){
A[0] = A[i]; //复制为哨兵
for(j=i-1; A[0] < A[j]; --j) //从后往前查找待插入位置
A[j+1] = A[j]; //向后挪动
A[j+1] = A[0]; //复制到插入位置
}
}
空间效率:空间复杂度=O(1)
时间效率: 平均时间复杂度=O(n²)
稳定性:插入排序是一种稳定的排序方法
3.算法优化
折半插入排序:先⽤折半查找找到应该插⼊的位置,再移动元素
当 low>high 时折半查找停⽌,应将 [low, i-1] 内的元素全部右移,并将 A[0] 复制到 low 所指位置 (即high+1)
当 A[mid]==A[0] 时,为了保证算法的“稳定性”,应继续在 mid 所指位置右边寻找插⼊位置
void InsertSort(int A[], int n){
int i,j,low,high,mid;
for(i=2;i<=n;i++){
A[0] = A[i]; //将A[i]暂存到A[0]
low = 1; high = i-1; //折半查找的范围
while(low<=high){
//折半查找
mid = (low + high)/2; //取中间点
if(A[mid]>A[0]) //查找左半子表
high = mid - 1;
else //查找右半子表
low = mid + 1;
}
for(j=i-1; j>high+1;--j) //统一后移元素,空出插入位置
A[j+1] = A[j];
A[high+<