归并排序(熟悉下)

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

  参考:https://www.cnblogs.com/chengxiao/p/6194356.html

package com.nrsc.sort;

public class MergeSort {
    public static void main(String[] args) {
        int[] arr = { 49, 38, 65, 97, 23, 22, 76, 1, 5, 8, 2, 0, -1, 22 };
        mergeSort(arr, 0, arr.length - 1);
        System.out.println("排序后:");
        for (int i : arr) {
            System.out.println(i);
        }
    }

    /**
     * 归并排序
     * 
     * @param arr
     * @param left
     * @param right
     */
    private static void mergeSort(int[] arr, int left, int right) {
        if (left < right) {

            // 取中间值
            int middle = (left + right) / 2;
            // 对中间值左边进行排序----不断拆分
            mergeSort(arr, left, middle);
            // 对中间值右边进行排序----不断拆分
            mergeSort(arr, middle + 1, right);
            // 将左右两个排好序的数组进行合并
            merge(arr, left, middle, right);
        }

    }

    /**
     * 左右两个排好序的数组进行合并 这两个数组在原arr中下标分别为
     * arr[left~,middle]和arr[middle+1,right]
     * 这里必须要非常明确(只有这里明确了,才能知道为什么会有注意点1和3)
     * 
     * @param arr    原始数组
     * @param left
     * @param middle
     * @param right
     */
    private static void merge(int[] arr, int left, int middle, int right) {

        // 新建一个临时数组用来存放排好序的数
        int[] tmp = new int[arr.length];
        
        //注意点1
        int ls = left;// 左边数组的第一个下标
        int ts = left;// 临时数组tmp的最左边的下标
        int rs = middle + 1; // 右边数组的第一个下标

        // 当两个数组都没到末尾时,谁小,将谁先放进临时数组tmp
        while (ls <= middle && rs <= right) {
            if (arr[ls] < arr[rs]) {
                tmp[ts++] = arr[ls++];
            } else {
                tmp[ts++] = arr[rs++];
            }
        }
        //注意点2
        // 能走到这里有两种情况,或者ls>middle了,或者rs>right了,
        // 也就是左边或右边至少有一个数组已经全部放到新数组tmp里了

        // 如果这时候ls<=middle,则此时ls~middle的值比已经放进tmp的数都大,只需将其依次放入tmp就好了
        while (ls <= middle) {
            tmp[ts++] = arr[ls++];
        }

        // 同理,如果此时rs<=righe,说明此时rs~right的值比已经放进tmp的数都大,只需将其依次放入tmp就好了
        while (rs <= right) {
            tmp[ts++] = arr[rs++];
        }
        //注意点3
        // 将tmp数组赋值给arr------tmp是有序数组
        while (left <= right) {
            arr[left] = tmp[left++];
        }

    }
}

 

posted @ 2021-07-28 21:29  LyAsano  阅读(45)  评论(0编辑  收藏  举报