2.2:归并排序

一:归并操作

在本节中我们所讨论的算法都基于归并这个简单的操作,即将两个有序数组归并成一个:

void sort(vector<int> &arr, int start, int mid, int end){
    int i=start, j= mid+1;
    vector<int> arrcopy;
    for (int k = 0; k <= end; ++k)
    {
        arrcopy.push_back(arr[k]);
    }
    for (int k = start; k <= end; ++k)
    {
        if (i > mid){ arr[k] = arrcopy[j++]; } //剩下的走完
        else if (j > end){ arr[k] = arrcopy[i++]; }
        else
        {
            //谁小谁走
            if (arrcopy[j] < arrcopy[i]){ arr[k] = arrcopy[j++]; }
            else{ arr[k] = arrcopy[i++]; }
        }                                    
    }
}

自顶向下的递归归并排序

class MergeSort
{
private:
    static vector<int> aux;//归并所需的辅助数组
public:

    static void merge(vector<int> &arr, int start, int mid, int end)
    {
        int i = start, j = mid + 1;
        vector<int> arrcopy;
        for (int k = 0; k <= end; ++k)
        {
            arrcopy.push_back(arr[k]);
        }
        for (int k = start; k <= end; ++k)
        {
            if (i > mid){ arr[k] = arrcopy[j++]; }
            else if (j > end){ arr[k] = arrcopy[i++]; }
            else
            {
                if (arrcopy[j] < arrcopy[i]){ arr[k] = arrcopy[j++]; }
                else{ arr[k] = arrcopy[i++]; }
            }
        }
    }
//首先记住,只有一个数的数组是有序的
//sort的递归调用只是负责把原数组分开,一直细分直到就剩下一个元素,即满足hi<=hi
//然后return,至此并无排序功能,排序的实现主要在merge,那么为什么要用递归分开呢?
//因为递归能最简单地做到入栈出栈效果,且分到最后,单个元素一定有序,然后再merge
    static void sort(vector<int> &arr, int start, int end)
    {
        if (start >= end){ return; }
        int mid = start + (end - start) / 2;
        sort(arr, start, mid);
        sort(arr, mid + 1, end);
        merge(arr, start, mid, end);
    }
};

自底向上的非递归归并排序

这个更好理解

class MergeSort
{
private:
    static vector<int> aux;//归并所需的辅助数组
public:

    static void merge(vector<int> &arr, int start, int mid, int end)
    {
        int i = start, j = mid + 1;
        vector<int> arrcopy;
        for (int k = 0; k <= end; ++k)
        {
            arrcopy.push_back(arr[k]);
        }
        for (int k = start; k <= end; ++k)
        {
            if (i > mid){ arr[k] = arrcopy[j++]; }
            else if (j > end){ arr[k] = arrcopy[i++]; }
            else
            {
                if (arrcopy[j] < arrcopy[i]){ arr[k] = arrcopy[j++]; }
                else{ arr[k] = arrcopy[i++]; }
            }
        }
    }

    static void sort(vector<int> &arr)
    {
        int N = arr.size();
        for (int sz = 1; sz < N; sz *= 2) //子数组每次是原来的两倍
        {
            for (int start = 0; start < N - sz; start += 2 * sz)
            {
                //最后一个子数组的大小只有在数组大小是sz的偶数倍的情况下等于sz,否则就小于
                merge(arr, start, start + sz - 1, min(start + 2 * sz - 1, N - 1));
            }
        }
    }
};
全部评论

相关推荐

评论
点赞
9
分享
牛客网
牛客企业服务