小白懂算法之归并排序

一.归并排序简介

  归并排序是一种概念上最简单的排序算法,与快速排序一样,归并排序也是基于分治法的。

二.算法原理

  归并排序将待排序的元素序列分成两个长度相等或接近相等的子序列,子序列中再分成两个子序列,直至子序列的个数为1.左子序列和右子序列需要排序合并成一个序列。合并两个子序列的过程也就是两路归并。

三.图解

四.代码实现(java实现)

    @Test
    public void test() throws InterruptedException{
        int[] arr = new int[10000];
        Random random = new Random();
        
        for(int i=0;i<10000;i++) {
            arr[i] = random.nextInt(100);
        }
        
        Date date1 = new Date();
        //辅助数组
        int[] temp = new int[arr.length];
        //调用归并排序方法
        mergeSort(arr,0,arr.length-1,temp);
        
        Date date2 = new Date();
        
        //输出时间差
        System.out.println(getDatePoor(date2,date1));
        
        System.out.println("排好序的数组:");
        for (int e : arr)
            System.out.print(e+" ");
    }

    private void mergeSort(int[] arr, int left, int right,int[] temp) {
        
        /**
         *     实现思路:
         *         1.若left>right,则逻辑上不成立
         *         2.计算left和right的中间值,用于分隔两个子序列
         *         3.递归遍历左子序列
         *         4.递归遍历右子序列
         *         5.两个子序列进行合并
         */
        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);
        }
    }

    private void merge(int[] arr, int left, int mid, int right,int[] temp) {
        /**
         *     合并的实现思路:
         *         使用一个辅助数组,用于临时存储合并的序列
         *         由于左子序列要和右子序列逐一比较,那么需要指针来记录他们的位置:
         *             》指针p1:指向左子序列的元素
         *             》指针p2:指向右子序列的元素
         *             》指针tp:指向辅助数组保存下标的值
         *         左子序列和右子序列逐一比较,小的加入到辅助数组的相应位置
         *         最后一定会存在一方的子序列剩下的情况,直接全部依次加入到辅助序列中,因为子序列是排过序的
         *         将辅助数组复制到原数组相应的位置
         */
        
        //三个指针
        int p1 = left;    //指向左子序列的元素
        int p2 = mid + 1; //指向右子序列的元素
        int tp = left; //指向辅助数组保存下标的值
        
        //比较大小,并加入到辅助数组中
        while(p1 <= mid && p2 <= right) {
            if(arr[p1] <= arr[p2])
                temp[tp++] = arr[p1++];
            else
                temp[tp++] = arr[p2++];
        }
        
        //存在一方序列剩下的情况,直接全部加入到辅助数组中
        while(p1 <= mid) temp[tp++] = arr[p1++];
        while(p2 <= right) temp[tp++] = arr[p2++];
        
        //将辅助数组复制到元素数组相应位置
        for(int i=left;i<=right;i++) {
            arr[i] = temp[i];
        }
        
    }
    

public static String getDatePoor(Date endDate, Date nowDate) {
 
    long nd = 1000 * 24 * 60 * 60;    //一天
    long nh = 1000 * 60 * 60;    //一小时
    long nm = 1000 * 60;    //一分钟
    long ns = 1000;    //1秒
    // 获得两个时间的毫秒时间差异
    long diff = endDate.getTime() - nowDate.getTime();
    System.out.println(diff);
    // 计算差多少天
    long day = diff / nd;
    // 计算差多少小时
    long hour = diff % nd / nh;
    // 计算差多少分钟
    long min = diff % nd % nh / nm;
    // 计算差多少秒//输出结果
    long sec = diff % nd % nh % nm / ns;
    
    long ms = diff % nd % nh % nm % ns;
    
    return day + "天" + hour + "小时" + min + "分钟"+sec+"秒"+ms+"毫秒";
}
}

参考资料:

  https://blog.csdn.net/qq_36442947/article/details/81612870

原文地址:https://www.cnblogs.com/ibcdwx/p/13993303.html