简单选择排序
- 时间复杂度 O(n^2)
- 空间复杂度 O(1)
- 稳定性 不稳定
- 基本思想 每趟循环从待排序元素中选出一个最小(最大)的元素排到i位置。直到n-1趟排序做完,数组有序。
代码实现
void selectSort(int *a, int n){
int min;
for(int i = 0; i < n - 1; i ++){
min = i;
for(int j = i + 1; j < n; j ++){
if(a[j] < min){
swap(a, j, min);
min = j;
}
}
}
}
堆排序
堆的定义:n个关键字序列称为堆,当且仅当该序列满足:
- L(i) >= L(2i) 且L(i) >= L(2i+1) -- 大根堆
- L(i) <= L(2i) 且L(i) <= L(2i+1) -- 小根堆
快速排序优于堆排序的原因:
- 快速排序对CPU缓存更友好
- 快速排序的比较次数少于堆排序
大根堆代码实现
//调整以k为根的树为大根堆
void heapAjust(int *a ,int n, int k){
int root = a[k];
int i = 2 * k + 1;
while(i < n){
if((i + 1) < n && a[i] < a[i + 1]){
i ++;
}
if(root < a[i]){
a[k] = a[i];
k = i;
i = 2 * i + 1; //更新子元素
}else{ //已k为根的树满足大根堆要求
break;
}
}
a[k] = root;
}
//初始化大根堆
void buildMaxHeap(int *a, int n){
for(int i = n / 2; i >= 0; i --){
heapAjust(a, n, k);
}
}
//删除堆顶元素
void remove(int *a, int n){
a[0] = a[n - 1];
heapAdjust(a, n, 0);
}
void heapSort(int *a, int n){
buildMaxHeap(a, n);
for(int i = n - 1; i > 0; i --){
swap(a, 0, i);
heapAjust(a, i, 0);
}
}
堆的典型应用
堆的典型应用可以看看极客上王争老师的《数据结构与算法》
- 求topK
- 求中位数
- 合并有序小文件
- 高性能定时器
求topK
基本思想:初始化含K的元素的小顶堆,遍历比较剩余数据,如果元素大于堆顶元素,则用该元素替换堆顶元素,并做一次堆化操作,否则继续比较下一个元素。