归并排序
分治法:
思路:
分治法的实质就是递归。
分支模式在每层递归时都有三个步骤:
- 分解原问题为若干个子问题,这些子问题是原问题的规模较小的实例
- 解决这些子问题,递归的求解各子问题。然而,若子问题的规模足够小,则直接求解。
- 合并这些子问题的解成原问题的解
即:
分解:分解待排序的n个元素的序列成各具n/2个元素的两个子序列
解决:使用归并排序递归的排序两个子序列
合并:合并两个已排序的子序列以产生已排序的答案
代码:
// 归并排序
public static void mergeSort(int[] arr, int p, int r){
if (p < r) {
int q = (p + r) / 2;
mergeSort(arr, p, q);
mergeSort(arr, q + 1, r);
merge(arr, p, q, r);
}
}
/**
* 分支排序
* @param arr 要排序的序列 第一个数组(p 左指针 q 右指针) 第二个序列(q 左指针 r 右指针)
* @return
*/
public static void merge(int[] arr, int p, int q, int r) {
// 左边数组的长度
int n1 = q - p + 1;
// 右边数组的长度
int n2 = r - q;
// 定义两个数组
int[] left = new int[n1 + 2];
int[] right = new int[n2 + 2];
// 将原数组中的元素插入两个子序列中
for (int i = 1; i <= n1; i++) {
left[i] = arr[p + i - 1];
}
for (int i = 1; i <= n2; i++) {
right[i] = arr[q + i];
}
left[n1 + 1]= 100000000;
right[n2 + 1]= 100000000;
// 将两个数组按顺序插入数组
int i = 1, j =1;
for(int k = p; k <= r; k++) {
if(left[i] <= right[j]) {
arr[k] = left[i];
i++;
} else {
arr[k] = right[j];
j++;
}
}
}