归并排序

246 阅读1分钟

归并排序

整体思路

递归将数组拆分成两份,直到不能拆分(实际就是左边数组一个元素,右边数组一个元素)进行merge,merge 后的结果和另外merge后的数组再merge。

易错点

变量定义: l 左侧起始位置,mid 中间位置,r 结束位置

  • 在merge过程中,因为copy了一个数组出来,左侧起始位置时0,右侧数组的起始下标应该等于左侧元素个数的值(因为数组下标是0开始)。我容易写成 r-mid 这样来计算右侧数组的起始位置
  • 在比较的过程中,判断右侧数组没有元素时,应该写成 rightIndex >= r

具体代码如下:

// 归并排序思路:将元素划分成两部分进行排序,排好序后进行合并,重复上面的过程

#include <stdio.h>
#include <vector>

using namespace std;

class MergeSortExe2 {
public:
    void sort(vector<int>& arr) {
        sort(arr, 0, (int)arr.size()-1);
    }
    
private:
    void sort(vector<int>& arr, int l, int r) {
        if (l>=r) {
            return;
        }
        
        int mid = l + (r - l)/2;
        sort(arr, l, mid);
        sort(arr, mid+1, r);
        merge(arr, l, mid, r);
    }
    
    /// merge过程:
    /// 先将[l...r]之间的元素拷贝出来
    /// 挨个比较[l...mid]和[mid+1...r]之间的元素大小,将比较后的结果放在原数组中
    void merge(vector<int>& arr, int l, int mid, int r) {
        vector<int> tempArray;
        for (int i=l; i<=r; i++) {
            tempArray.push_back(arr[i]);
        }
        
        /// 计算左、右两边数组各有多少个数
        int leftNum = mid-l+1;
        int leftIndex = 0;
        int rightNum = r-mid;
//        int rightIndex = r-mid-1; ///!!!错误的写法,如果右侧数组只有2个元素,左侧100个,比较及拷贝的过程都是用的左边数组。。。
        int rightIndex = leftNum;
        int k = l;
        /// 只要两个数组中还有数据,就需要做拷贝动作
        while (leftIndex < leftNum || rightIndex < rightNum) {
            ///第一步处理左边数组已经没有元素的情况
            ///第二部处理右边数组已经没有元素的情况
            ///第三部比较第一个数组中的元素是否小于第二个数组中的元素
            ///第四步将第二个数组中的元素拷贝到原数组中
            if (leftIndex >= leftNum) {
                arr[k] = tempArray[rightIndex];
                rightIndex++;
                k++;
//            } else if(rightIndex >= rightNum) { /// !!!错误的写法,应该比较小于数组大小即可
            } else if(rightIndex >= tempArray.size()) {
                arr[k] = tempArray[leftIndex];
                leftIndex++;
                k++;
            } else if(tempArray[leftIndex] <= tempArray[rightIndex]) {
                arr[k] = tempArray[leftIndex];
                leftIndex++;
                k++;
            } else {
                arr[k] = tempArray[rightIndex];
                rightIndex++;
                k++;
            }
        }
    }
};