前言:
学算法,先排序,今天就来学习排序算法中的王中王,不但复杂度低,而且没有特殊情况,怎么滴都好,哈哈,你能把我怎么样?
归并排序
归并排序的核心思想是分治递归,其主要步骤是
1. 将数列复制,再将复制的数列分为两个数列,左一半和右一半。
2. 分别对左一半数列和右一半数列进行排序。
3. 然后将两个数列合并,主要是设置三个指针,原数列指针k和左半边指针i、右半边指针j,指针都从数列头部开始往后指。比较指针i处和j处的值,若i处值小,则原数列k处值为左i处值,且i = i + 1, 否则原数列k处值为右j处值,j = j + 1, 最后k = k + 1.
4. 不断重复1 到 3 部,直到数列只有两个元素。
void merge(int *a, int *aux, int lo, int mid, int hi){
int k;
for(k = 0; k <= hi; k++){
aux[k] = a[k];
}
int i = lo, j = mid + 1;
for(k = lo; k <= hi; k++){
if(i > mid){
a[k] = aux[j];
j = j + 1;
}
else{
if(j > hi){
a[k] = aux[i];
i = i + 1;
}
else{
if(aux[j] < aux[i]){
a[k] = aux[j];
j = j + 1;
}
else{
a[k] = aux[i];
i = i + 1;
}
}
}
}
}
void sort(int *a, int *aux, int lo, int hi){
int i;
if(hi <= lo){
return;
}
int mid = lo + (hi - lo) / 2;
sort(a, aux, lo, mid);
sort(a, aux, mid + 1, hi);
if(a[mid + 1] >= a[mid]){
return;
}
merge(a, aux, lo, mid, hi);
}
运行一下:
#include <stdio.h>
#include <iostream>
using namespace std;
int main()
{
int i;
int a[10] = {5, 7, 4, 3, 6, 9, 0, 1, 2, 8};
int aux[10];
sort(a, aux, 0, 9);
for(i = 0; i < 10; i++){
cout << a[i] << " ";
}
cout << endl;
}
结果:
0 1 2 3 4 5 6 7 8 9
总结:
归并排序是一种稳定的排序。对于长度为n的数列,需进行logn趟二路归并,每趟归并的时间为O(n),故其时间复杂度无论是在最好情况下还是在最坏情况下均是O(nlogn)。 算法需要一个辅助向量来暂存两有序子文件归并的结果,故其辅助空间复杂度为O(n)。
最后强烈推荐Coursera上普林斯顿大学的算法课点击打开链接
以上内容纯属个人学习总结,不代表任何团体或单位。若有理解不到之处请见谅!