1.归并算法图解

2.归并算法代码
bash
package com.suanfa.sort;
import java.util.Arrays;
/**
* 归并算法
*/
public class MergeSort {
/**
* 拆的时间复杂度logn * 并的时间复杂度n = nlogn
*
* @param arr
* @param left
* @param right
*/
public static void sortMerge(int[] arr, int left, int right) {
//相等了就表示只有一个数了 不用再拆了
if (left < right) {
//取中间值进行拆分
int mid = (left + right) / 2;
//左边拆分(从右往左拆分),拆的过程的时间复杂度是logn(从右往左拆分)
sortMerge(arr, left, mid);
//右边拆分(从左往右拆分)
sortMerge(arr, mid + 1, right);
//这里合并值是从右边开始合并(因为这里是栈先执行后返回后执行的先返回),等栈回溯到最后一次时就相当于拆成两个一起合并了
merge(arr, left, mid, right);
System.out.println(Arrays.toString(arr));
}
}
/**
* 并的时间复杂度为n
*
* @param arr
* @param left
* @param mid
* @param right
*/
public static void merge(int[] arr, int left, int mid, int right) {
//临时数组,用来存放合并的有序数据
int[] temp = new int[arr.length];
//分割左边的开始位置
int point1 = left;
//分割右边开始位置
int point2 = mid + 1;
//这里为什么是left,因为这里排序是从左边到右边结束,所以开始值是left
int tempIndex = left;
//将左边和右边合并,使用插入排序,终止条件时左边的开始位置到左边边界,右边到右边边界
while (point1 <= mid && point2 <= right) {
if (arr[point1] < arr[point2]) {
temp[tempIndex] = arr[point1];
point1++;
} else {
temp[tempIndex] = arr[point2];
point2++;
}
tempIndex++;
}
//如果左边的位置小于或者等于左边的边界值,说明左边的值还有数据没有放入到临时数组中
// 这里一般会有一个数据还没有放进去,因为最后一个数据是没有数据可比较了
while (point1 <= mid) {
temp[tempIndex] = arr[point1];
point1++;
tempIndex++;
}
//这里是放入右边还没有放入的数据
while (point2 <= right) {
temp[tempIndex] = arr[point2];
point2++;
tempIndex++;
}
//总结:这里左边和右边只可能有一边需要放入,因为最后剩一个数据要么是左边的要么是右边的
//这里为什么是left开始right结束,以为排序是从left开始right结束的
for (int i = left; i <= right; i++) {
arr[i] = temp[i];
}
}
public static void main(String[] args) {
int arr[] = {9, 5, 6, 8, 0, 3, 7, 1};
sortMerge(arr, 0, arr.length - 1);
}
}