归并排序

 1 package com.zha.wmls.sort;
 2 
 3 /**
 4  * @ClassName MergerSort
 5  * @Desc 归并排序,采用先分后治的思想
 6  * @Author wmls
 7  * @Date 2021/6/21 10:29
 8  * @Version 1.0
 9  */
10 public class MergerSort {
11     public static void main(String[] args) {
12         //测试效率
13         int[] arr = new int[8000000];
14         for (int i = 0; i < 80000; i++) {
15             arr[i] = (int) (Math.random()*80000000);
16         }
17         int[] temp = new int[arr.length];
18         long beforTime = System.currentTimeMillis();
19         mergerSort(arr, 0, arr.length-1, temp);
20         long afterTime = System.currentTimeMillis();
21         System.out.println(afterTime-beforTime); // 350ms左右
22     }
23 
24     /**
25      * 通过边分边治的思想,并不是所有分完之后再治,
26      */
27     public static void mergerSort(int[] arr, int left, int right, int[] temp){
28         if (left < right){
29             int middle = (left + right)/2;
30             //左边分,直到分到最小
31             mergerSort(arr, left, middle, temp);
32             //右边分
33             mergerSort(arr, (middle+1), right, temp);
34             //当前面两个递归都不成立时执行一次,一共执行right次
35             sort(arr, left, right, middle, temp);
36         }
37     }
38     /**
39      *
40      * @param arr  需要排序的数组
41      * @param left  左边数组第一位的下标
42      * @param right  数组最右边的下标,可用于判断右边的数据是否到达最后一个
43      * @param middle   用于找到右边第一个数的下标和判断左边数据是否到达最后一个
44      * @param temp  临时数组,用来临时存放排序完成的数
45      */
46     //编码格式,多个参数逗号后面必须有空格
47     private static void sort(int[] arr, int left, int right, int middle, int[] temp){
48         int l = left;
49         //无论是奇数还是偶数个,均分后都是左边个数≤右边
50         int r = middle+1;
51         int t = 0;
52         //排序,当有一边已经没有数据时跳出
53         while (l <= middle && r <= right){
54             if(arr[l] < arr[r]){
55                 temp[t] = arr[l];
56                 t++;
57                 l++;
58             }else {
59                 temp[t] = arr[r];
60                 t++;
61                 r++;
62             }
63         }
64         //此时左边下标还没有到最后一个,把左边剩余数据存入temp
65         while (l <= middle){
66             temp[t] = arr[l];
67             t++;
68             l++;
69         }
70         //与上面同理,右边下标还没到最后一个,把右边剩余数据存入temp
71         while (r <= right){
72             temp[t] = arr[r];
73             t++;
74             r++;
75         }
76         //将排序好的temp数组放回原数组
77         t = 0;
78         /*
79          * 不能这样写,因为每一次治都会利用temp数组,而temp数组的下标是从零开始,
80          * 而且每一次使用到的temp数组的下标为0~right
81          * arr数组的下标每次都从left到right,
82          */
83 //        while (t < arr.length){
84 //            arr[t] = temp[t];
85 //            t++;
86 //        }
87         int tempLeft = left;
88         while (tempLeft <= right){
89             arr[tempLeft] = temp[t];
90             t += 1;
91             tempLeft += 1;
92         }
93     }
94 }

个人心得:算法最重要的就是要自己写,尤其是用到了递归,先写出来,再debug,慢慢的整个流程就会清楚许多

posted @ 2021-06-21 15:02  wmls  阅读(77)  评论(0)    收藏  举报