zoukankan      html  css  js  c++  java
  • 归并排序(Merge Sort)

    归并排序是颇受欢迎的排序算法,因为他的时间复杂度恒为O(n log(n))。顾名思义,这个排序算法就是将多个排好序的数组合并成单个排好序的数组。

    具体步骤如下:

    • 将待排序的数组分成左右两部分。
    • 再将这两部分分别分成左右两部分。
    • 一直分下去,直到不可分(每部分只有一个元素)。
    • 由于数组被分成许多的单个数据,比较起来就简单了,然后开始合并,合并的同时排序。
    • 持续合并直到得到排好序的数组。

    下面这幅图可以帮助你理解算法过程:

    merge_sort

    上图中可以看到,算法将数组分为两个部分,然后再分,一直分到只有一个元素,然后合并成已排序的数组。

    将两个已排序的数组合并成一个排序的数组的方法在前面已经讨论过了,不清楚的同学看一下

    怎样合并排序数组(How to merge 2 sorted arrays?)

    归并排序显然可以用分治法,算法如下:

    # split in half
    m = n / 2

    # recursive sorts
    sort a[1..m]
    sort a[m+1..n]

    # merge sorted sub-arrays using temp array
    b = copy of a[1..m]
    i = 1, j = m+1, k = 1
    while i <= m and j <= n,
        a[k++] = (a[j] < b[i]) ? a[j++] : b[i++]
    → invariant: a[1..k] in final position
    while i <= m,
        a[k++] = b[i++]
    → invariant: a[1..k] in final position

    算法实现:

    #include<stdio.h>
     
    //defining a function to merge 2 sorted arrays
    //note that the 2 arrays will be contained in a single array
    //as the left and right part
    void merge(int arr[], int start, int mid, int end)
    {
        // the array is as:- {start, ... ..mid, mid+1, .....end}
        // thus there are 2 arrays we need to merge
     
        //1st array , starting index and last index
        int i = start;
        int l1 = mid;
     
        //2nd array , starting index and last index
        int j = mid+1;
        int l2 = end;
     
        //create an auxiliary array to store the elements
        int len = end-start + 1;
        int *arr2 = (int *)malloc(sizeof(int)*len);
        int k = 0;
     
        //apply the algorithm to merge 2 sorted arrays
        while(i<=l1 && j<=l2)
        {
            if(arr[i] < arr[j])
                arr2[k++] = arr[i++];
            else
                arr2[k++] = arr[j++];
        }
     
        while(i<=l1)
            arr2[k++] = arr[i++];
        while(j<=l2)
            arr2[k++] = arr[j++];
     
        //copy the auxiliary array to original array
        for(k = 0; k<len; k++)
            arr[start++] = arr2[k];
     
        //free the memory
        free(arr2);
    }
     
    // a function to perform merge sort on an array with the given
    // starting and ending index
    void performMergeSort(int arr[], int start, int end)
    {
        if(start<end)
        {
            //to get the middle of the array
            int mid = start + (end - start) / 2;
     
            //recursively dividing the left and right parts
            performMergeSort(arr, start, mid);  /* left part */
            performMergeSort(arr, mid+1, end);  /* right part */
     
            //finally we need to merge them
            merge(arr, start, mid, end);
        }
    }
     
    //defining a function to perform merge sort on array arr[] of given size
    void mergeSort(int arr[], int size)
    {
        performMergeSort(arr, 0, size-1);
    }
     
    // driver function to test the above function
    int main(void)
    {
        int i;
        int arr[10] = {2, 6, 4, 10, 8, 1, 9, 5, 3, 7};
     
        mergeSort(arr,10);
     
        printf("SORTED array:- ");
        for(i=0;i<10;i++)
            printf("%d ",arr[i]);
     
        return 0;
    }

    Time Complexity: O(n log(n)) for all cases
    Space Complexity: O(n) for the Sortauxiliary array

  • 相关阅读:
    leetcode 1301. 最大得分的路径数目
    LeetCode 1306 跳跃游戏 III Jump Game III
    LeetCode 1302. 层数最深叶子节点的和 Deepest Leaves Sum
    LeetCode 1300. 转变数组后最接近目标值的数组和 Sum of Mutated Array Closest to Target
    LeetCode 1299. 将每个元素替换为右侧最大元素 Replace Elements with Greatest Element on Right Side
    acwing 239. 奇偶游戏 并查集
    acwing 238. 银河英雄传说 并查集
    acwing 237程序自动分析 并查集
    算法问题实战策略 MATCHORDER 贪心
    Linux 安装Redis全过程日志
  • 原文地址:https://www.cnblogs.com/programnote/p/4723564.html
Copyright © 2011-2022 走看看