归并排序(mergesort)

前言:

比较有名气的排序算法有八种,前面我们已经学习了几种排序,下面我们来学习新的一种排序——归并排序。

归并排序

归并排序的核心思想是分治递归,其主要步骤是

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上普林斯顿大学的算法课点击打开链接

以上内容纯属个人学习总结,不代表任何团体或单位。若有理解不到之处请见谅!

猜你喜欢

转载自blog.csdn.net/qq_39747794/article/details/81915109