• (十三)排序——归并


    1. 归并排序介绍:

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

    2. 归并排序思想示意图-基本思想:

    3. 归并排序思想示意图-合并相邻有序子序列:

    再来看看治阶段,我们需要将两个已经有序的子序列合并成一个有序序列,比如上图中的最后一次合并,要将[4,5,7,8]和[1,2,3,6]两个已经有序的子序列,合并为最终序列[1,2,3,4,5,6,7,8],来看下实现步骤

    4. 归并排序的应用实例:

    给你一个数组, val arr =Array(8, 4, 5, 7, 1, 3, 6, 2 ), 请使用归并排序完成排序。

    • 代码实现(韩老师)
    import java.text.SimpleDateFormat;
    import java.util.Arrays;
    import java.util.Date;
    public class MergetSort {
    
        public static void main(String[] args) {
            //int arr[] = { 8, 4, 5, 7, 1, 3, 6, 2 }; //
            //测试快排的执行速度
            // 创建要给 80000 个的随机的数组
            int[] arr = new int[8000000];
            for (int i = 0; i < 8000000; i++) {
                arr[i] = (int) (Math.random() * 8000000); // 生成一个[0, 8000000) 数
            }
            System.out.println("排序前");
            Date data1 = new Date();
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String date1Str = simpleDateFormat.format(data1);
            System.out.println("排序前的时间是=" + date1Str);
            int temp[] = new int[arr.length]; //归并排序需要一个额外空间
            mergeSort(arr, 0, arr.length - 1, temp);
    
            Date data2 = new Date();
            String date2Str = simpleDateFormat.format(data2);
            System.out.println("排序前的时间是=" + date2Str);
            //System.out.println("归并排序后=" +Arrays.toString(arr));
        }
    
        //分+合方法
        public static void mergeSort(int[] arr, int left, int right, int[] temp) {
            if (left < right) {
                int mid = (left + right) / 2; //中间索引
                //向左递归进行分解
                mergeSort(arr, left, mid, temp);
                //向右递归进行分解
                mergeSort(arr, mid + 1, right, temp);
                //合并
                merge(arr, left, mid, right, temp);
            }
        }
    
        //合并的方法
    
        /**
         * @param arr   排序的原始数组
         * @param left  左边有序序列的初始索引
         * @param mid   中间索引
         * @param right 右边索引
         * @param temp  做中转的数组
         */
        public static void merge(int[] arr, int left, int mid, int right, int[] temp) {
    
            int i = left; // 初始化 i, 左边有序序列的初始索引
            int j = mid + 1; //初始化 j, 右边有序序列的初始索引
            int t = 0; // 指向 temp 数组的当前索引
            //(一)
            //先把左右两边(有序)的数据按照规则填充到 temp 数组
            //直到左右两边的有序序列,有一边处理完毕为止
            while (i <= mid && j <= right) {//继续
                //如果左边的有序序列的当前元素,小于等于右边有序序列的当前元素
                //即将左边的当前元素,填充到 temp 数组
                //然后 t++, i++
                if (arr[i] <= arr[j]) {
                    temp[t] = arr[i];
                    t += 1;
                    i += 1;
                } else { //反之,将右边有序序列的当前元素,填充到 temp 数组
                    temp[t] = arr[j];
                    t += 1;
                    j += 1;
                }
            }
            //(二)
            //把有剩余数据的一边的数据依次全部填充到 temp
            while (i <= mid) { //左边的有序序列还有剩余的元素,就全部填充到 temp
                temp[t] = arr[i];
                t += 1;
                i += 1;
            }
            while (j <= right) { //右边的有序序列还有剩余的元素,就全部填充到 temp
                temp[t] = arr[j];
                t += 1;
                j += 1;
            }
            //(三)
            //将 temp 数组的元素拷贝到 arr
            //注意,并不是每次都拷贝所有
            t = 0;
            int tempLeft = left; //
            //第一次合并 tempLeft = 0 , right = 1 // tempLeft = 2 right = 3 // tL=0 ri=3
            //最后一次 tempLeft = 0 right = 7
            while (tempLeft <= right) {
                arr[tempLeft] = temp[t];
                t += 1;
                tempLeft += 1;
            }
        }
    
    }
    
    • 代码实现(自己)
    public class MergeSort {
    
        public static void main(String[] args) {
    
            /*int[] arr = {8, 4, 5, 7, 1, 3, 6, 2};
            int[] temp = new int[arr.length];
            mergeSort(arr, 0, arr.length - 1, temp);*/
    
            int[] arr = new int[10000000];
            int[] temp = new int[arr.length];
            for (int i = 0; i < 10000000; i++) {
                arr[i] = (int) (Math.random() * 1000000000);
            }
    
            long t1 = System.currentTimeMillis();
            mergeSort(arr, 0, arr.length - 1, temp);
    
            System.out.println(System.currentTimeMillis() - t1);
            //System.out.println(Arrays.toString(arr));
        }
    
        /**
         * 拆分+合并
         *
         * @param arr
         * @param left
         * @param right
         * @param temp
         */
        public static void mergeSort(int[] arr, int left, int right, int[] temp) {
            if (left < right) {
                int mid = (left + right) / 2;
    
                //左边拆分
                mergeSort(arr, left, mid, temp);
    
                //右边拆分
                mergeSort(arr, mid + 1, right, temp);
    
                //合并
                merge(arr, left, mid, right, temp);
            }
        }
    
        /**
         * 合并
         *
         * @param arr
         * @param left
         * @param mid
         * @param right
         * @param temp
         */
        public static void merge(int[] arr, int left, int mid, int right, int[] temp) {
            int i = left;
            int j = mid + 1;
            int t = 0;
            while (i <= mid && j <= right) {
                if (arr[i] <= arr[j]) {
                    temp[t] = arr[i];
                    i++;
                    t++;
                } else {
                    temp[t] = arr[j];
                    j++;
                    t++;
                }
            }
    
            //左边没有遍历完,剩余全部添加至temp
            while (i <= mid) {
                temp[t] = arr[i];
                t++;
                i++;
            }
    
            //右边没有遍历完,剩余全部添加至temp
            while (j <= right) {
                temp[t] = arr[j];
                t++;
                j++;
            }
    
            //拷贝temp至原数组
            t = 0;
            int tempLeft = left;
            while (tempLeft <= right) {
                arr[tempLeft] = temp[t];
                tempLeft++;
                t++;
            }
    
        }
    }
    
    
  • 相关阅读:
    Java自带工具jstack故障分析的一个案例
    当spring 容器初始化完成后执行某个方法
    tomcat的maxThreads、acceptCount(最大线程数、最大排队数)
    RESTful API 设计指南
    GitHub简单使用入门
    Newton's method
    把一个文件夹下的多个excel文件合并到同一个excel的一个sheet里
    multimap的使用 in C++,同一个关键码存在多个值
    pandas把多个sheet读进一个DataFrame
    数据预处理之Minkowski距离计算
  • 原文地址:https://www.cnblogs.com/everyingo/p/15009372.html
Copyright © 2020-2023  润新知