前提:
- 输入:待排序数组和元素个数
- 无输出,一般是从小到大排序
- 稳定性:任意两个相等的数据,排序前后相对位置不改变
- 算法无优劣,分情况讨论
每次交换相邻两元素
冒泡排序
外层共循环n次,每次归位一个最大的数字;每次交换消去一个逆序对,如果序列基本有序,简单高效
// 冒泡排序
void Bubble(ElementType A[], int N)
{
for (int i = N - 1; i > 0; i--){
int flag = 0;
for (int j = 0; j < i; j++){
if (A[j] > A[j + 1]){
Swap(A[j], A[j + 1]);
flag = 1;//表示发生了交换
}
}
if (flag == 0) break;//全程无交换,数组已经有序
}
}
直接插入排序
外层共循环n次,每次插入一个数字;每次交换消去一个逆序对,如果序列基本有序,简单高效
// 插入排序
void Insertion(ElementType A[], int N){
for (int i = 1; i < N; i++){
int temp = A[i]; // 摸下一张牌
int j;
for (j = i; j > 0 && A[j - 1] > temp; j--) // 在已排序序列中从后向前查找插入位置,如果新牌比当前的牌小
A[j] = A[j - 1]; // 挪出空位,继续向前比较,直至碰到小于等于新牌的牌
A[j] = temp; // 新牌落位
}
}
二分插入排序
也是一种插入排序,与直接插入排序不同的是查找插入位置时不是从后向前依次查找,而是使用二分查找的方式,内循环次数减少,在速度上有一定提升
希尔排序
使用类似插入排序的方式,将间隔n个元素的序列进行插入排序,通过不断减小间隔,使序列基本有序,最后1间隔插入排序,得到结果
选择排序
每次在数组未排序的部分中寻找最小值,放到已排序数组的最后,这样循环N次排序就完成了;排序的快慢取决于寻找最小元的快慢
//选择排序
void Selection(ElementType A[], int N){
for (int i = 0; i < N;i++){
//从A[i]到A[N-1]中寻找最小元,将值赋给min
ElementType min = Min(A, i, N - 1);
//将未排序部分最小元换到有序部分的最后位置
swap(A[i], A[min]);
}
}
堆排序
借助最小堆,建造最小堆后每次弹出最小的元素,按照顺序放到临时数组中,最后再复制到原数组中
归并排序
快速排序
表排序
如果待排序元素是很大的结构体,则使用表排序,用一个数组来储存正确元素顺序的下标,而无需频繁移动元素在原数组中的位置
习题 insert or marge
p124-127