美文网首页
归并排序

归并排序

作者: 00d1ed2b53ae | 来源:发表于2019-01-07 13:57 被阅读10次

    归并排序(Merge sort)是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。
    作为一种典型的分而治之思想的算法应用,归并排序的实现由两种方法:

    自下而上的迭代;

    和选择排序一样,归并排序的性能不受输入数据的影响,但表现比选择排序好的多,因为始终都是 O(nlogn) 的时间复杂度。代价是需要额外的内存空间。
    算法步骤

    申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列;
    设定两个指针,最初位置分别为两个已经排序序列的起始位置;
    比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置;
    重复步骤 3 直到某一指针达到序列尾;
    将另一序列剩下的所有元素直接复制到合并序列尾。

    /**
     *归并排序
     */
    int L[10];    // 两个子数组定义成全局变量(辅助存储空间,大小正比于元素的个数)
    int R[10];
    void merge(int A[], int left, int middle, int right)// 合并两个已排好序的数组A[left...middle]和A[middle+1...right]
    {
        int n1 = middle - left + 1;     // 两个数组的大小
        int n2 = right - middle;
        for (int i = 0; i < n1; i++)    // 把两部分分别拷贝到两个数组中
            L[i] = A[left + i];
        for (int j = 0; j < n2; j++)
            R[j] = A[middle + j + 1];
        L[n1] = INT_MAX;                // 使用无穷大作为哨兵值放在子数组的末尾
        R[n2] = INT_MAX;                // 这样可以免去检查某个子数组是否已读完的步骤
        int i = 0;
        int j = 0;
        for (int k = left; k <= right; k++) // 依次比较两个子数组中的值,每次取出更小的那一个放入原数组
        {
            if (L[i] <= R[j])
            {
                A[k] = L[i];
                i++;
            }
            else
            {
                A[k] = R[j];
                j++;
            }
        }
        
    }
    
    void mergesort_recursion(int A[], int left, int right) // 递归实现的归并排序(自顶向下)
    {
        int middle = (left + right) / 2;
        if (left < right)          // 当待排序的序列长度为1时(left == right),递归“开始回升”
        {
            mergesort_recursion(A, left, middle);
            mergesort_recursion(A, middle + 1, right);
            merge(A, left, middle, right);
        }
    }
    
    void mergesort_iteration(int A[], int left, int right)  // 非递归(迭代)实现的归并排序(自底向上)
    {
        int low, middle, high;    // 子数组索引,前一个为A[low...middle],后一个子数组为A[middle+1...high]
        for (int size = 1; size <= right - left; size *= 2) // 子数组的大小初始为1,每轮翻倍
        {
            low = left;
            while (low + size - 1 <= right - 1 )// 后一个子数组存在(需要归并)
            {
                middle = low + size - 1;    
                high = middle + size;        
                if (high > right)              // 后一个子数组大小不足size
                    high = right;
                merge(A, low, middle, high);
                low = high + 1;                 // 前一个子数组索引向后移动
            }
        }
    }
    
    

    相关文章

      网友评论

          本文标题:归并排序

          本文链接:https://www.haomeiwen.com/subject/gdrurqtx.html