各种排序算法概览
Posted xytpai
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了各种排序算法概览相关的知识,希望对你有一定的参考价值。
快速排序(交换范式)
快速排序代码基本上背一遍就可以了,注意>=和<=个人认为不加也可以但是可能会超时。
// 一趟快排就是找到第一个元素的位置使得左边比它小右边比它大
int _quicksort(int *a, int low, int high) {
int mid_value = a[low];
while(low < high) {
while(low < high && a[high] >= mid_value) high--;
a[low] = a[high];
while(low < high && a[low] <= mid_value) low++;
a[high] = a[low];
}
a[low] = mid_value;
return low;
}
void quicksort(int *a, int low, int high) {
if (low < high) {
int mid = _quicksort(a, low, high);
quicksort(a, low, mid-1);
quicksort(a, mid+1, high);
}
}
冒泡排序(交换范式)
void bubblesort(int *a, int n) {
for(int i=0; i<n-1; i++) {
int flag = 0;
for(int j=n-1; j>i; j--) {
if (a[j-1] > a[j]) {
int tmp = a[j-1];
a[j-1] = a[j];
a[j] = tmp;
flag = 1;
}
}
if (!flag) return;
}
}
直接插入排序(插入范式)
比较简单就不贴代码了,就是从数组a的第二个元素开始往后迭代,找到一个值后插入到前面使整个数组有序。
希尔排序(插入范式)
代码题也不需要写,举例一趟增量为3排序子过程:
第0步 15 9 7 8 20 -1 4
第1步 15 8 4 -> 4 8 5
第2步 9 20 -> 9 20
第3步 7 -1 -> -1 7
(每一步都用直接插入排序获取)
第一趟得到: 4 9 -1 8 20 7 5
在此基础上,希尔排序遵循如下过程:
- 从增量为n/2开始,逐趟增量减少一半进行上述操作,直到增量最终为1那一趟结束。
选择排序(选择范式)
非常简单,如果从小到大排,从索引0开始到结束,每一步选择后面最小的放在当前索引位置。
堆排序(选择范式)
推排序把数组看作一颗完全二叉树,大根堆意思是这颗二叉树的任何父节点永远大于子节点。
完全二叉树就是数组的每个元素依次填入一个完整的二叉树。
建大根堆过程:
- 从最后一个非叶结点开始,自底向上调整每一个非叶节点(从右向左从下到上)
- 调整操作:如果当前节点比两个儿子都大无需调整,否则找到最大的那个儿子把值与自己交换,再调整那个儿子直到叶结点。
堆排序过程(建完堆后):
void heapsort(int *a, int n) {
build_maxheap(a, n);
for(int i=n-1; i>0; i--) {
swap(a[0], a[i]); // 从后往前迭代,每次将堆顶输出到当前位置, 排序后为从小到大
adjust(a, i-1);
}
}
归并排序
归并算法还是比较重要的,建议背一下,其功能是归并两个本来就有序的数组,使输出有序。
void merge(int *a, int low, int mid, int high, int *buffer) {
// a[low:mid] 与 a[mid+1:high] 各自有序, 现在要输出一个有序的a[low:high]
int i, j, k;
for (k=low; k<=high; k++) buffer[k] = a[k]; //拷贝
for (i=low, j=mid+1, k=low; k<=mid && j<=high; k++) {
// i,j为两个有序数组的扫描指针, k为当前输出指针
if (buffer[i] <= buffer[j]) a[k] = buffer[i++];
else a[k] = buffer[j++];
}
while(i<=mid) a[k++] = buffer[i++];
while(j<=high) a[k++] = buffer[j++];
}
int *buffer = new int[n] // 需要开一个和输入一样大的数组
void mergesort(int *a, int low, int high) {
if (low<high) {
int mid = (low+high)/2;
mergesort(a, low, mid);
mergesort(a, mid+1, high);
merge(a, low, mid, high, buffer); //归并放最后,这个算法是自底向上的
}
}
基数排序
十进制基,优先低位基数排序过程:
- 建立10个队列
- 按照输入所有数最后一位(%10),放入这些队列(比如123就放入3号队列队尾)
- 从0~10将各个队列里的值输出
- 再按照倒数第二位放入队列(与2操作相似)
- 从0~10将各个队列里的值输出
- 一直继续直到最高位操作结束
排序算法特性表
算法 | 最好复杂度 | 平均复杂度 | 最坏复杂度 | 空间复杂度 | 稳定性 |
---|---|---|---|---|---|
直接插入排序 | O(n) | O(n^2) | O(n^2) | O(1) | Y |
冒泡排序 | O(n) | O(n^2) | O(n^2) | O(1) | Y |
选择排序 | O(n^2) | O(n^2) | O(n^2) | O(1) | |
希尔排序 | O(1) | ||||
快速排序 | O(nlogn) | O(nlogn) | O(n^2) | O(logn) | |
堆排序 | O(nlogn) | O(nlogn) | O(nlogn) | O(1) | |
2路归并排序 | O(nlogn) | O(nlogn) | O(nlogn) | O(n) | Y |
基数排序 | O(d(n+r)) | O(d(n+r)) | O(d(n+r)) | O(r) | Y |
以上是关于各种排序算法概览的主要内容,如果未能解决你的问题,请参考以下文章