zoukankan      html  css  js  c++  java
  • 五、归并排序

    归并排序,首先需要用到递归,递归这个东西说难不难,说简单也挺烦的。

    一、递归是什么

    递归从代码直观的表现来看,就是自己调用自己。比如这样:

     public int recursive(int a){
            return a+recursive(a++);
        }

    这样就是一个递归,但是问题是这样会无线递归下去。所以必须给他一个出口:

        public static void main(String[] args) {
            System.out.println(recursive(0));
        }
    
        public static int recursive(int a) {
            if (a > 10) return 0;//当a大于10的时候直接返回
            return a + recursive(++a);
        }

    这个递归就是个从1加到10的结果,重点不在递归,递归就到这里。

    二、归并排序

    什么是归并排序?首先我们假定这个数组可以分成两半,而且在这两个半个数组中是排好顺序的,然后将这两个数组合并。

    package test;
    
    /**
     * <p></p>
     *
     * @author zy 刘会发
     * @version 1.0
     * @since 2020/4/14
     */
    public class MergeSort {
        public static void main(String[] args) {
            int[] a = new int[]{1, 3, 5, 7, 2, 4, 6};
            sort(a);
            print(a);
        }
    
        public static void sort(int arr[]) {
            merge(arr);
        }
    
        public static void merge(int arr[]) {
            int mid = arr.length / 2 + 1;//数组的中间位置;
            int[] temp = new int[arr.length];//定一个中间数组
    
            int i = 0;//左边数组开始的位置
            int j = mid;//右边数组开始的位置
            int k = 0;//新数组开始的位置
    
            while (i < mid && j < arr.length) {
                if (arr[i] <= arr[j]) {//如果左边的小将左边的值放到新数组中
                    temp[k] = arr[i];
                    i++;//下标加一
                } else {
                    temp[k] = arr[j];//否者右边的放到新数组中
                    j++;
                }
                k++;//新数组下标加一
            }
    
            //可能在上边的合并完后原数组中还有为合并的数值
            while (i < mid) temp[k++] = arr[i++];//将左半个数组中数值复制到新数组中
            while (j < arr.length) temp[k++] = arr[j++];//将右半个数组中数值复制到新数组中
    
            for (int m = 0; m < temp.length; m++) {//将新的数组中的值复制到原数组中
                arr[m] = temp[m];
            }
        }
    
        public static void print(int arr[]) {//打印
            for (int i = 0; i < arr.length; i++) {
                System.out.printf("%d,", arr[i]);
            }
        }
    }

    上诉代码是假定两个半个数组中都已经排好顺序了,但是实际情况并不会是这种情况的,所以这样的代码一定是不可以的,还需要修改!

    package test;
    
    /**
     * <p></p>
     *
     * @author zy 刘会发
     * @version 1.0
     * @since 2020/4/14
     */
    public class MergeSort {
        public static void main(String[] args) {
            int[] a = new int[]{1, 3, 5, 7, 2, 4, 6};
            sort(a);
            print(a);
        }
    
        public static void sort(int arr[]) {
            merge(arr, 0, 4, arr.length);
        }
    
        /**
         * <p>因为合并可能会重任意一个位置开始,任意一个位置结束,所以需要指定几个参数<p/>
         *
         * @param arr        要排序的数组
         * @param leftPro    左指针 包含
         * @param rightPro   右指针 包含
         * @param rightBound 右边界 不包含
         */
        public static void merge(int arr[], int leftPro, int rightPro, int rightBound) {
            int mid = rightPro - 1;//数组的中间位置;
            int[] temp = new int[rightBound - leftPro];//定一个中间数组
    
            int i = leftPro;//左边数组开始的位置
            int j = rightPro;//右边数组开始的位置
            int k = 0;//新数组开始的位置
    
            while (i <= mid && j < rightBound) {
                if (arr[i] <= arr[j]) {//如果左边的小将左边的值放到新数组中
                    temp[k] = arr[i];
                    i++;//下标加一
                } else {
                    temp[k] = arr[j];//否者右边的放到新数组中
                    j++;
                }
                k++;//新数组下标加一
            }
    
            //可能在上边的合并完后原数组中还有为合并的数值
            while (i <= mid) temp[k++] = arr[i++];//将左半个数组中数值复制到新数组中
            while (j < rightBound) temp[k++] = arr[j++];//将右半个数组中数值复制到新数组中
    
            for (int m = 0; m < temp.length; m++) {//将新的数组中的值复制到原数组中
                arr[leftPro + m] = temp[m];
            }
        }
    
        public static void print(int arr[]) {//打印
            for (int i = 0; i < arr.length; i++) {
                System.out.printf("%d,", arr[i]);
            }
        }
    }

    那么这样修改就灵活一些了,可以再数组任何位置进行合并了,既然是归并排序,那么接下来就是递归了。

    package test;
    
    /**
     * <p></p>
     *
     * @author zy 刘会发
     * @version 1.0
     * @since 2020/4/14
     */
    public class MergeSort {
        public static void main(String[] args) {
            int[] a = new int[]{1, 3, 5, 7,2,4,6};
            sort(a, 0, a.length-1);
            print(a);
        }
    
        /**
         * <p>对sort方法进行递归</p>
         *
         * @param arr   要排序的数组
         * @param left  左边开始的位置
         * @param right 右边结束的位置
         */
        public static void sort(int arr[], int left, int right) {
    
            if (left == right) return;//递归的出口,如果开始的位置和结束的位置相同,那么只有一个元素,直接返回即可
    
            //首先将数组分成两个部分
            int mid = (left + right) / 2;
            //先对左边的进行排序
            sort(arr, left, mid);
            //然后对右边的进行排序
            sort(arr, mid + 1, right);
            //合并两个排好顺序的数组
            merge(arr, left, mid + 1, right);
        }
    
        /**
         * <p>因为合并可能会重任意一个位置开始,任意一个位置结束,所以需要指定几个参数<p/>
         *
         * @param arr        要排序的数组
         * @param leftPro    左指针 包含
         * @param rightPro   右指针 包含
         * @param rightBound 右边界 不包含
         */
        public static void merge(int arr[], int leftPro, int rightPro, int rightBound) {
            int mid = rightPro - 1;//数组的中间位置;
            int[] temp = new int[rightBound - leftPro];//定一个中间数组
    
            int i = leftPro;//左边数组开始的位置
            int j = rightPro;//右边数组开始的位置
            int k = 0;//新数组开始的位置
    
            while (i <= mid && j <= rightBound) {
                if (arr[i] <= arr[j]) {
                    temp[k++] = arr[i++];
                } else {
                    temp[k++] = arr[j++];
                }
            }
    
            //可能在上边的合并完后原数组中还有为合并的数值
            while (i <= mid) temp[k++] = arr[i++];//将左半个数组中数值复制到新数组中
            while (j <= rightBound) temp[k++] = arr[j++];//将右半个数组中数值复制到新数组中
    
            for (int m = 0; m < temp.length; m++) {//将新的数组中的值复制到原数组中
                arr[leftPro + m] = temp[m];
            }
        }
    
        public static void print(int arr[]) {//打印
            for (int i = 0; i < arr.length; i++) {
                System.out.printf("%d,", arr[i]);
            }
        }
    }
  • 相关阅读:
    bzoj2748:[HAOI2012]音量调节
    bzoj2287:[POJ Challenge]消失之物
    bzoj1485:[HNOI2009]有趣的数列
    Codeforces 620E New Year Tree
    CF813E Army Creation
    527D.Clique Problem
    4337: BJOI2015 树的同构
    Codeforces Round #443 (Div. 1) C. Tournament
    [BZOJ4913][SDOI2017]遗忘的集合
    [八省联考2018]林克卡特树lct
  • 原文地址:https://www.cnblogs.com/Tiandaochouqin1/p/12697853.html
Copyright © 2011-2022 走看看