分治策略
分治策略:将原问题分解成为若干个规模较小而结构与原问题相似地子问题,递归地解决这些子问题,然后再合并其结果,就得到原问题的解。
这形而上的解释并不能让你立刻理解什么是分治?这就像武功秘籍的总纲,只告诉你了这武学的精髓,但是你要能真正理解并运用它还需要具体的招式口诀。要真正掌握分治还得不断地练习,学习一些运用了分治策略地经典算法,就像这合并排序算法。
合并排序算法思想
- 将n个元素分成各含n/2个元素的子序列
- 递归执行步骤1,直到每个序列元素只有一个
- 至下而上地将序列两两排序合并
如何递归地将数组一分为二
俗话说的好,离开代码讲算法都是耍流氓(手动滑稽)。先列出部分代码。
// n=0,m=10
public static void sort1(int[] arr,int n,int m){
if(n<m) {
int p = (m+n)/2; // 语句1
sort1(arr,n,p); // 递归1
sort1(arr,p+1,m); // 递归2
merge(arr,n,p,m); // 这行先不看
}
}
这个方法体现了分治策略,将数组不断地一分为二,以n<m为结束条件,当n>=m时说明每个子序列中仅有一个元素。
本方法的实现流程如图所示:
合并/排序子序列
合并和排序的思想:由于sort方法已经将子序列分割,当然不是实际的分割,只是逻辑上的,传入的参数p,q,r将一段序列分为两份已排序的子序列,把这两个子序列排序合并成一个序列。
合并代码:
public static void merge(int[] arr,int p,int q,int r) {
int max = Integer.MAX_VALUE;
int n1 = q-p+1;
int n2 = r-q;
int[] L = new int[n1+1];
int[] R = new int[n2+1];
for(int i = 0 ;i < n1;i++) {
L[i] = arr[p+i];
}
for(int j = 0;j < n2;j++) {
R[j] = arr[q+j+1];
}
L[n1] = max;
R[n2] = max;
int i = 0;
int j = 0;
for(int k = p;k <= r;k++) {
if(L[i] <= R[j]) {
arr[k] = L[i];
i++;
}else {
arr[k] = R[j];
j++;
}
}
}
合并排序算法总代码
import java.util.Arrays;
public class Demo8 {
public static void main(String[] args) {
int[] arr = new int[] {1,3,5,7,4,2,9,8,10,6};
Util.sort1(arr,0,9);
System.out.println(Arrays.toString(arr));
}
}
class Util{
public static void merge(int[] arr,int p,int q,int r) {
int max = Integer.MAX_VALUE;
int n1 = q-p+1;
int n2 = r-q;
int[] L = new int[n1+1];
int[] R = new int[n2+1];
for(int i = 0 ;i < n1;i++) {
L[i] = arr[p+i];
}
for(int j = 0;j < n2;j++) {
R[j] = arr[q+j+1];
}
L[n1] = max;
R[n2] = max;
int i = 0;
int j = 0;
for(int k = p;k <= r;k++) {
if(L[i] <= R[j]) {
arr[k] = L[i];
i++;
}else {
arr[k] = R[j];
j++;
}
}
}
public static void sort1(int[] arr,int n,int m){
if(n<m) {
int p = (m+n)/2;
sort1(arr,n,p);
sort1(arr,p+1,m);
merge(arr,n,p,m);
}
}
}
如果有表达错误希望大家能告诉我,对你有帮助地话点个赞哦。