归并排序介绍
归并排序是利用归并的思想实现的排序方法,该算法采用经典的分治(divide-and-conquer)策略(分治法将问题分成一些小的问题然后递归求解,而治的阶段则将分的阶段得到的各答案“修补”在一起,即分而治之)。
图解
代码
import java.util.Arrays;
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);
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数组的当前索引
while (i <= mid && j <= right) {
if(arr[i] <= arr[j]) {
temp[t] = arr[i];
t += 1;
i += 1;
}else{
temp[t] = arr[j];
t += 1;
j += 1;
}
}
while( i <= mid) {
temp[t] = arr[i];
t += 1;
i += 1;
}
while(j <= right) {
temp[t] = arr[j];
t += 1;
j += 1;
}
t = 0;
int tempLeft = left;
while(tempLeft <= right) {
arr[tempLeft] = temp[t];
t += 1;
tempLeft += 1;
}
}
}
调试
另外大家在敲代码的时候可能会对递归执行的顺序产生疑惑,这里建议大家使用调试功能,本人敲代码的环境为Idea,接下来为大家简单演示一下调试的过程。
1.设置断点
选定要设置断点的代码行,在行号的区域后面单击鼠标左键即可。
2.开启调试会话
点击图中像爬虫一样的图标。
IDE下方出现Debug视图,左边的内容是现在调试程序停留的代码行,方法mergeSort()中,程序的第16行。右边的区域是程序的方法调用栈区。在这个区域中显示了程序执行到断点处所调用过的所用方法,越下面的方法被调用的越早。
3.单步调试(step into)
点击红色箭头指向的按钮,程序向下执行一行(如果当前行有方法调用,这个方法将被执行完毕返回,然后到下一行)
按这个方法一直执行下去,观察变量的值对应进行到哪一步,慢慢了解递归往下执行的步骤。
分析
归并排序是一种稳定的排序。
(1)时间复杂度
对长度为n的文件,需进行趟二路归并,每趟归并的时间为O(n),故其时间复杂度无论是在最好情况下还是在最坏情况下均是O(nlogn)。
(2)空间复杂度
需要一个辅助向量来暂存两有序子文件归并的结果,故其辅助空间复杂度为O(n),显然它不是就地排序。
最后
文章学习来源:https://www.bilibili.com/video/BV1E4411H73v?p=71
(尚硅谷java数据结构)