分治法的思想:将原问题分解为几个规模较小但类似于原问题的子问题,递归的求解这些子问题,然后再合并这些子问题的解来建立原问题的解。
分治模式在每层递归时都有三个步骤:
1、分解原问题为若干子问题,这些子问题是原问题规模较小的实例;
2、解决这些子问题,递归的求解各子问题。然而,若子问题的规模足够小,则直接求解;
3、合并这些子问题的解成原问题的解。
package algorithm.merge;
import java.util.Random;
/**
* 归并算法
* @author Administrator
* @Date 2018/04/25
*/
public class MergeSort {
public static void main(String[] args) {
int[] arr = new int[20];
Random rand = new Random();
for (int i = 0; i < arr.length; i++) {
arr[i] = rand.nextInt(1000);
}
print(arr);
mergeSort(arr, 0 , arr.length-1);
print(arr);
}
/**
* 归并算法排序
* @param arr
* @param start
* @param end
*/
public static void mergeSort(int[] arr, int start, int end) {
if(start < end) {
int middle = (start + end) / 2;
mergeSort(arr, start, middle);
mergeSort(arr, middle+1, end);
merge(arr, start, middle, end);
}
}
/**
* 分治思想:数组arr左侧数组数据有序,右侧数组数据有序
* @param arr
* @param start 起始下标
* @param middle 中间隔离下标
* @param end 终点下标
*/
public static void merge(int[] arr, int start, int middle, int end) {
int[] L = new int[middle - start + 1]; // 数组middle左侧数据数组
int[] R = new int[end - middle]; // 数组middle右侧数据数组
// 对middle左侧数据数组赋值
for(int i = 0; i < L.length; i++) {
L[i] = arr[start + i];
}
// 对middle右侧数据数组赋值
for(int i = 0; i < R.length; i++) {
R[i] = arr[middle + i + 1];
}
// 合并:将左右两边有序的数组合并为一个有序数组
int i = 0;
int j = 0;
int k = start;
while(k <= end) {
if(i >= L.length) {
arr[k] = R[j++];
} else if (j >= R.length) {
arr[k] = L[i++];
} else if (L[i] >= R[j]) {
arr[k] = R[j++];
} else {
arr[k] = L[i++];
}
k++;
}
}
/**
* 打印输出
* @param arr
*/
public static void print(int[] arr) {
System.out.print("arr: ");
for(int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
System.out.println();
}
}