一:基本思想
该算法采用经典的分治策略,分治法将问题分成一堆小的问题,而治的阶段则将各个阶段得到的答案合并到一起。也就是分到不可再分,再进行排序,俩个单独数进行排序合并成一组,不同组之间再进行排序合并,直到全部排序合并完成。
二:图解+文字
1)将数组分成不可再分的阶段
2)治的阶段(大白话解释)
(1)最终分成单独的数
8 4 5 7 1 3 6 2 合并4次(8和4,5和7,1和3,6和2)
(2)俩组比较大小,从小到大放到新数组里,全部比较完成后,新数组复制回原数组
4,8 5,7 1,3 2,6 合并2次
(3)俩组俩组比较,同(2)
4,5,7,8 1,2,3,6 合并1次
(4)最后一次比较,同(2)
1,2,3,4,5,6,7,8
通过如上的分析,可以得到
共合并 :7 次=数据总长-1
三:优缺点
优点:稳定的排序算法
预测的性能比较好
缺点:占用的空间较多,当数据量特别大的时候,备用数组会占用额外的内存(看代码示例)
不适用于小型数据集
四:代码实现
简洁明了,代码每一步都有注释
import java.util.Arrays;
public class MergetSort {
public static void main(String[] args) {
int[] arr={8,4,5,7,1,3,6,2};
//temp 对应备用数组
int[] temp=new int[arr.length];
mergeSort(arr,0, arr.length-1, temp);
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);
}
}
//合并的函数
public static void merge(int[] arr,int left,int mid,int right,int[] temp){
//定义左面数组开始循环的下标
int i=left;
//定义右面数组开始循环的下标
int j=mid+1;
//定义数组temp的初始下标
int k=0;
//第一步:把左右俩边的(有序)数组按照规则填充到temp数组里面
//直到有一边数组填充完毕
while (i <= mid && j <= right){
if (arr[i] <= arr[j]){
temp[k++]=arr[i++];
}else{
temp[k++]=arr[j++];
}
}
//第二步,将剩余未填充完毕的数组全部填充到temp中
while (i <= mid){
temp[k++]=arr[i++];
}
while (j <= right){
temp[k++]=arr[j++];
}
//第三步:temp数组赋值到arr数组里面
//注: 并不是从头全部拷贝回到arr数组里面,
/* 原因:
* 如上分成了不同组,当填充前俩个 8 和 4的时候,tempLeft=0,right=1
* 填充5 和 7 的时候,tempLeft=2,right=3
* 填充1 和 3 的时候,tempLeft=4,right=5
* 填充 4 8 和 5 7 的时候,tempLeft=0,right=3
* 填充 1 3 和 2 6 的时候,tempLeft=4,right=7
* 最后依次才是0 和 7
* 每次填充的数都是temp下标对应的位置
*/
int t=0;
int tempLeft=left;
while (tempLeft <= right){
arr[tempLeft]=temp[t];
tempLeft+=1;
t+=1;
}
}
}