归并排序

更多内容,前往 IT-BLOG

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

一、归并排序的思想


【1】如下图,可以看到这种结构很像一棵完全二叉树,本文的归并排序我们采用递归去实现(也可采用迭代的方式去实现)。分阶段可以理解为就是递归拆分子序列的过程。

【2】归并排序思想示意图2(合并相邻有序子序列):再来看看治阶段,我们需要将两个已经有序的子序列合并成一个有序序列,比如上图中的最后一次合并,要将[4,5,7,8]和[1,2,3,6]两个已经有序的子序列,合并为最终序列[1,2,3,4,5,6,7,8],来看下实现步骤:会使用到一个临时内存变量temp;

二、归并排序案例


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

 1 package com.algorithms;
 2 
 3 import java.util.Arrays;
 4 
 5 /**
 6  * 归并排序
 7  */
 8 public class MergeSort {
 9     public static void main(String[] args) {
10         int arr[] = new int[]{5,4,6,3,7,2,8,9,1,0,8,3};
11         MergeSort mergeSort = new MergeSort();
12         mergeSort.mergeSort(arr,0,arr.length-1,new int[arr.length]);
13         System.out.printf(Arrays.toString(arr));
14     }
15 
16     //分解数据 + 合并数据
17     public void mergeSort(int arr[],int left,int right,int[] temp){
18         if(left < right){
19             int mid = (left + right)/2;
20             //传入左区间
21             mergeSort(arr,left,mid,temp);
22             //传入右区间
23             mergeSort(arr,mid+1,right,temp);
24             //合并
25             merge(arr,left,mid,right,temp);
26         }
27     }
28 
29     /*
30      * 合并方法思想:【1】、将left——mid 之间的数据 与 mid+1——right 之间的数据进行比较,并顺序的放到 temp 中;
31      * 【2】上述结束后,情况一:右边的数据遍历结束,但是左边的数据还有时,将左边的全部数据复制到temp中;
32      *                 情况二:左边的数据遍历结束,但是右边的数据还有时,将右边的全部数据复制到temp中;
33      */
34     public void merge(int[] arr,int left,int mid,int right,int[] temp){
35         //temp的下标
36         int t = 0;
37         //left 的值后续要用这里暂存起来
38         int l = left;
39         //因为右边的元素对mid进行了操作,所以这里需要获取传入的mid并锁死
40         int m = mid;
41         while(left <= m && mid+1 <= right){
42             if(arr[left] < arr[mid+1]){
43                 temp[t] = arr[left];
44                 t++;
45                 left++;
46             }else{
47                 temp[t] = arr[mid+1];
48                 t++;
49                 mid++;
50             }
51         }
52         //情况一
53         while(left <= m){
54             temp[t] = arr[left];
55             t++;
56             left++;
57         }
58         //情况二
59         while(mid+1 <= right){
60             temp[t] = arr[mid+1];
61             mid++;
62             t++;
63         }
64         //将temp的值复制到arr中
65         //先将temp的下标还原
66         t=0;
67         while(l <= right){
68             arr[l] = temp[t];
69             t++;
70             l++;
71         }
72     }
73 }

三、总结


速度仅次于快速排序,为稳定排序算法,一般用于对总体无序,但是各子项相对有序的数列。 归并排序比较占用内存,但却是一种效率高且稳定的算法。改进归并排序在归并时先判断前段序列的最大值与后段序列最小值的关系再确定是否进行复制比较。如果前段序列的最大值小于等于后段序列最小值,则说明序列可以直接形成一段有序序列不需要再归并,反之则需要。所以在序列本身有序的情况下时间复杂度可以降至O(n)。传统归并排序的算法复杂度是O(nlogn)

posted @ 2020-11-16 21:07  Java程序员进阶  阅读(126)  评论(0编辑  收藏  举报