数据结构与算法学习之路:归并排序

什么是归并排序?

归并排序:建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。

主要思想为:将已有序的子序列合并,得到完全有序的序列。

简单来说:就是将待排序序列分为若干个最小子序列(子序列长度为1或2),先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。

归并排序过程图如下:

算法思想

正如我们所知,最普通的排序算法,其思想类似于穷举法,即遍历待排序数列,每一个元素都与数列中的元素作对比,找到相应的位置,故时间复杂度一般为O(n^2)。而归并排序采用的则是“分而治之”的思想,即:先将待排序数列不断地向下二分,获得最终的最简子数列,将子序列排序,在不断合并子序列。

这样做的好处在哪呢?向下二分使得子序列的分解时间下降为O(lgn),而传统方法的分解时间为O(n)。很多人可能就很奇怪了,为什么说传统方法的分解时间是O(n)啊?

拿冒泡排序来说吧,冒泡排序中,其实就是不断将长度为n的数列分为长度为1和长度为n-1的两个子序列,拿长度为1的序列不断与n-1序列中的每一个元素作比较,找到最合适的位置。

而在子序列的排序过程中,虽然归并排序和传统排序相似,时间复杂度均为O(n),但事实上,归并排序中元素多余的移动会更少一些(当然,优化后的冒泡排序效果差不多,详见:Click Me!!!)。

具体代码

我这里只是写了一个最简单的实现,在写的过程中我考虑了很多优化的方案,以后会和大家分享哒~

    #include <stdio.h>

    #define MAX 5

    void merge(int a[], int start, int end,int result[]);

    int main(){
        int start = 0;
        int end = MAX - 1;
        int a[MAX] = { 2, 3, 8, 6, 1 };
        int result[MAX];

        merge(a, start, end, result);

        for (int i = 0; i < MAX; i++){
            printf("%d", result[i]);
        }

        getchar();
    }

    void merge(int a[], int start, int end, int result[]){
        int mid = (end + start) / 2;

        if (end - start == 1){
            if (a[start] > a[end]){
                int temp = a[start];
                a[start] = a[end];
                a[end] = temp;
            }
        }else if (end - start <= 0){
        }else{
            merge(a, start, mid, result);
            merge(a, mid + 1, end, result);

            int pointerA = start;
            int pointerB = mid + 1;

            for (int i = start; i < (end - start + 1); i++){
                if (a[pointerA] < a[pointerB]){
                    if (pointerA <= mid ){
                        result[i] = a[pointerA];
                        pointerA++;
                    }
                    else{
                        result[i] = a[pointerB];
                        pointerB++;
                    }
                }
                else{
                    if (pointerB <= end){
                        result[i] = a[pointerB];
                        pointerB++;
                    }
                    else{
                        result[i] = a[pointerA];
                        pointerA++;
                    }
                }
            }
        }
    }

你可能感兴趣的:(算法,归并排序)