排序算法之Merge Sort

Merge Sort 根本思路(设计算复杂度为 T(n)):

1) 序列一分为二 //计算复杂度为O(1);

2) 子序列递归排序 //计算复杂度为 2*T(n/2);

3) 合并有序子序列 // 计算复杂度为 O(n);

因此可以得出 T(n) = 2*T(n/2) + O(n);

则可得 T(n) = O(n*log(n))

在归并排序中最核心的问题就是如何合并两个有序的序列,我们利用的方法是二路归并算法。

简单来说就是:只比较两个序列的开头位置,取出其中小的那一个,然后循环运行,知道两个序列归并到一起。

一下是C语言的代码:

//
//  main.c
//  mergeSortV2
//
//  Created by HanXia on 18/3/14.
//  Copyright © 2018年 HanXia. All rights reserved.
//

#include <stdio.h>
void merge(int *a, int lo, int mid, int hi);
void mergeSort(int *a, int lo, int hi){
    if (hi - lo <= 1){
        return;
    }
    else {
        int mid = (hi + lo) >> 1;
        //将问题一分为二
        mergeSort(a, lo, mid); //递归调用mergeSort函数
        mergeSort(a, mid,hi);  //递归调用mergeSort函数
        merge(a, lo, mid, hi); //归并两个序列
    }
}
//二路归并算法
void merge(int *a, int lo, int mid, int hi){
    int lb = mid - lo;
    //定义B数组将一部分数据copy出来 以下C数组为a[mid,hi] A[lo, hi]
    int B[lb];
    for(int i = 0; i < lb; i++){
        B[i] = a[lo + i];
    }
    //因为我们并没有开辟新的C数组,所以当B 插入完毕后算法结束
    //同时一下判断 hi <= k 与 k < hi 相当于在 a[hi] 设置为一个无穷大的数
    //以便于在C归并完后可以顺利归并B数组在正确的位置
    for(int i = lo, j = 0, k = mid; j < lb;){
        if (hi <= k || B[j] <= a[k]){ //这里的a[k]为C数组部分
            //B 数组中的首相小于等于C数组中首相(注如果此时数组C以及插入完毕,则总是成立)
            a[i] = B[j];  //取出B数组中的首相
            j++;
            i++;
        }
        if (k < hi && a[k] < B[j]){ //
            a[i] = a[k];
            i++;
            k++;
        }
    }
}

int main(int argc, const char * argv[]) {
    int a [10] = {1, 2, 4, 5, 3, 2, 5, 8, 10, 1};
    int lo = 2;
    int hi = 8;
    mergeSort(a, lo, hi);
    for(int i = lo ; i < hi; i++){
        printf("a[%d] = %d\n",i,a[i]);
    }
    return 0;
}

输出为:

a[2] = 2
a[3] = 3
a[4] = 4
a[5] = 5
a[6] = 5
a[7] = 8

猜你喜欢

转载自blog.csdn.net/u010622506/article/details/79555122
今日推荐