归并排序

基本思想:

1)首先需要一个临时空间temp用来存放合并后的元素,长度为排列好的元素总个数。

2)取两个指针,分别为左右部分数组的头元素。

3)比较指针指向元素,将较小(较大)的那个放入temp(注意相等时不做元素位置交换),并将两指针向后移动一个step。

4)循环步骤3直到其中一段数组没有剩余元素(其中一段被遍历完)。

5)将还有元素剩余的另外一半数组元素直接放入temp尾部

代码实现:

    public static void merge(int[] list, int left, int mid, int right) {
        int len = right - left + 1;
        int[] temp = new int[len];       //辅助空间O(n)
        int l = left;
        int r = mid + 1;
        int index = 0;
        while (l <= mid && r <= right) {
            temp[index++] = (list[l] <= list[r] ? list[l++] : list[r++]);  // 带等号保证归并排序的稳定性
        }
        while (l <= mid) {
            temp[index++] = list[l++];
        }
        while (r <= right) {
            temp[index++] = list[r++];
        }
        System.arraycopy(temp, 0, list, left, len);
    }

    //递归
    public static void recSort(int[] list, int left, int right) {
        if (left < right) {
            int mid = (left + right) / 2;
            recSort(list, left, mid);
            recSort(list, mid + 1, right);
            merge(list, left, mid, right);
        }
    }

    //非递归
    public static void nonRecSort(int[] list, int len) {
        int left, mid, right;
        for (int i = 1; i < len; i *= 2) //初始以1个元素为单位,每轮操作元素数翻倍
        {
            left = 0;
            while (left + i < len) // 后半段仍有元素剩余
            {
                mid = left + i - 1;
                right = mid + i < len ? mid + i : len - 1;// 确定后半段尾部位置
                merge(list, left, mid, right);
                left = right + 1;
            }
        }

时间复杂度:

  最优情况:O(nlogn)

  最差情况:O(nlogn)

  平均:O(nlogn) 

空间复杂度:

     O(n)

稳定性:

  稳定

posted @ 2017-09-18 21:44  JOYZzzzz  阅读(112)  评论(0编辑  收藏  举报