简单排序
文章目录
- 简单排序
-
- [9.1 基础概念](#9.1 基础概念)
- [9.2 冒泡排序(稳定)](#9.2 冒泡排序(稳定))
- [9.3 插入排序(稳定)](#9.3 插入排序(稳定))
- [9.4 时间复杂度下界](#9.4 时间复杂度下界)
- [9.5 内容补充](#9.5 内容补充)
9.1 基础概念
排序算法的函数头(统一格式):void x_sort( element_type A[], int N )
- 大多数情况下,为简单起见,讨论从小到大的整数排序
- 稳定性:任意两个相等数据,排序前后的相对位置不发生改变
- N是正整数
9.2 冒泡排序(稳定)
基本思想:
- 把相邻的两个元素两两比较,如果顺序错误就交换
- 下一轮只需要处理上一轮处理的最后一个元素之外的部分(最后一个必然最大或最小)
- 重复这个过程
代码实现:
时间复杂度:
- 最好情况:O(N)
- 最坏情况:O(N2)
c
void bubble_sort(element_type A[], int N)
{
int i, p;
for (p = N - 1; p > 0; p--){ //最多只需要n-1次就可以排好
int flag = 0;
for (i = 0; i < p; i++){
if (A[i] > A[i+1]){
swap(A[i], A[i+1]);
flag = 1;
}
}
if (!flag) break; //全程无交换
}
}
9.3 插入排序(稳定)
基本思想(以整理手牌类比):
- 从第二张牌开始,把它插到前面已经排好序的牌堆里
- 插入时,逐个比较,将比它大/小的牌一次后移,找到合适位置插入
- 重复这个过程,直至所有牌整理好
代码实现:
时间复杂度:
- 最好情况:顺序 T = O( N )
- 最坏情况:逆序 T = O( N2 )
c
void insertion_sort(element_type A[], int N)
{
int p, i;
element_type temp;
for (p = 1; p < N; p++){
temp = A[p]; //取出未排序序列中的第一个元素
for (i = p; i > 0 && A[i-1] > temp; i--){
A[i] = A[i-1]; //依次与已排序序列中元素比较并右移
}
A[i] = temp; //放进合适位置
}
}
9.4 时间复杂度下界
-
对于下标 i < j,如果A[i] > A[j](默认从小到大排序),则称(i, j)是一对逆序对(inversion)
- 插入排序和冒泡排序每次交换,消掉一个逆序对
-
定理:任意N个不同元素组成的序列平均具有N(N - 1) / 4个逆序对
-
定理:任何仅以交换相邻两元素来排序的算法,其平均时间复杂度为Ω(N2)