码迷,mamicode.com
首页 > 编程语言 > 详细

归并排序

时间:2018-12-31 19:05:42      阅读:210      评论:0      收藏:0      [点我收藏+]

标签:数组指针   amp   完成   元素   答案   经典的   深度   完全   有序   

归并排序是利用归并思想实现的排序方法,该算法采用经典的分治策略,即将问题分成一些小的问题然后递归求解,而治的阶段则将分的阶段得到的答案“修补”在一起,即分而治之。

具体到排序,分阶段可以理解为递归拆分子序列的过程,递归深度为log2^N;
举例:
                8 4 5 7 1 3 6 2
        8 4 5 7                1 3 6 2
    8 4        5 7        1 3        6 2
         8                  4         5                  7          1                   3         6                  2
---------------------------------------------------------------------------------------------
    4 8        5 7        1 3        2 6
        4 5 7 8                1 2 3 6
                1 2 3 4 5 6 7 8
---------------------------------------------------------------------------------------------
而在治的阶段,我们需要将两个已经有序的子序列合并成一个有序序列,比如上面的最后一次合并,要将[4 5 7 8]和[1 2 3 6]两个已经有序的子序列合并为最终序列[1 2 3 4 5 6 7 8],步骤如下:
1.指针i指向第一个子序列开头4,指针j指向第二个子序列开头1,创建临时序列tmp;
2.1<4,将1填入tmp,右移j;
3.2<4,将2填入tmp,右移j;
4.3<4,将3填入tmp,右移j;
5.4<6,将4填入tmp,右移i;
6.继续重复这种比较+填入的操作,直到第二个子序列已经走完,这时将第一个子序列中剩余的7和8依次填入;
7.最后,将tmp中内容全部拷贝到原数组中,排序完成。

示例代码:
public class Test {

    public static void main(String[] args) {
        
        int[] arr = {6, 3, 8, 2, 9, 1};
        System.out.println("排序前数组为:");
        for(int i : arr) {
            System.out.print(i + ", ");
        }
        System.out.println();
        sort(arr);
        
        System.out.println("排序后数组为:");
        for(int i : arr) {
            System.out.print(i + ", ");
        }
        
    }
    
    public static void sort(int[] arr) {
        int[] tmp = new int[arr.length];
        sort(arr, 0, arr.length-1, tmp);
    }
    
    public static void sort(int[] arr, int left, int right, int[] tmp) {
        if(left < right) {
            int mid = (left + right)/2;
            sort(arr, left, mid, tmp); //左边归并排序,使得左子序有序
            sort(arr, mid+1, right, tmp); //右边归并排序,使得右子序有序
            merge(arr, left, mid, right, tmp); //将两个有序子数组合并操作
        }
    }
    
    public static void merge(int[] arr, int left, int mid, int right, int[] tmp) {
        int i = left; //左序列指针
        int j = mid + 1; //右序列指针
        int t = 0; //临时数组指针
        while(i <= mid && j <= right) {
            if(arr[i] <= arr[j]) {
                tmp[t++] = arr[i++];
            } else {
                tmp[t++] = arr[j++];
            }
        }
        while(i<=mid) { //将左边剩余元素填充进tmp
            tmp[t++] = arr[i++];
        }
        while(j<=right) { //将右边剩余元素填充进tmp
            tmp[t++] = arr[j++];
        }
        t=0;
        while(left <= right) { //将tmp中的元素全部拷贝到arr中
            arr[left++] = tmp[t++];
        }
    }

}

归并排序是稳定排序,也是一种十分高效的排序;
其中合并操作的平均时间复杂度为O(n),而完全二叉树的深度为log2^N,则总的平均时间复杂度为O(Nlog2^N);
空间复杂度为O(1)。

归并排序

标签:数组指针   amp   完成   元素   答案   经典的   深度   完全   有序   

原文地址:https://www.cnblogs.com/yuanfei1110111/p/10202567.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!