算法设计思想
分治法字面上理解就是“分而治之”,把一个复杂的问题分解成两个或者多个相似的问题,再把子问题分成更小的子问题,直到子问题可以简单的直接求解,原问题的解即子问题解的合并。
分治法的基本步骤:
1.分解:将原问题分解为若干个子问题;
2.解决:若子问题规模较小而比较任意解决,否则继续分解为更小的子问题,直到分解到能够解决掉的子问题;
3.合并:将已求解的子问题逐步合并为原问题的解。合并的代价因情况不同有很大的差异,分治法的有效性很大程度上依赖于合并的实现。
典型例题
一、归并排序
利用归并技术将一组数据按升序排列。
import java.util.Scanner;
public class _归并排序 {
private static int arr[];
public static void main(String[] args) {
System.out.println("输入元素的个数:");
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
System.out.print("请依次输入每个元素:");
arr = new int[n+1];
for (int i = 1; i <= n; i++) {
int nextInt = scanner.nextInt();
arr[i]=nextInt;
}
System.out.println("输入的序列:");
Print(arr);
Merge_SortDC(1,n);
System.out.println("排列后的序列:");
Print(arr);
}
// 用分治法对arr[low...high]进行二路归并
private static void Merge_SortDC(int low, int high) {
int mid;
if (low<high) {
mid=(low+high)/2; // 分解
Merge_SortDC(low, mid); // 递归对数组排序
Merge_SortDC(mid+1, high);
Merge(low,mid,high); // 组合,将两个有序区归并为一个有序区
}
}
// 实现二路归并过程
private static void Merge(int low, int mid, int high) {
int i=low,j=mid+1,p=0;
int[] arrs = new int[arr.length]; // arrs用于接收排序
while (i<=mid && j<=high) {
arrs[p++]=(arr[i]<arr[j])?arr[i++]:arr[j++];
}
while (i<=mid) {
arrs[p++]=arr[i++];
}
while (j<=high) {
arrs[p++]=arr[j++];
}
for (p= 0,i=low; i<=high; p++,i++) {
arr[i]=arrs[p];
}
}
// 遍历数组
private static void Print(int[] arr) {
for (int i = 1; i < arr.length; i++) {
System.out.print(arr[i]+" ");
}
System.out.println();
}
}
运行结果
二、快速排序
利用快速技术,实现对数据的从小到大的排列。
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class _快排 {
private static List<Integer> list = new ArrayList<Integer>();
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("输入元素个数:");
int num = scanner.nextInt();
System.out.print("依次输入每个元素:");
for (int i = 1; i <= num; i++) {
int n = scanner.nextInt();
list.add(n);
}
System.out.println("输入的序列:");
Print(list);
sort(list);
System.out.println("排列后的序列:");
Print(list);
}
private static void sort(List<Integer> items) {
if (items.size() > 1) {
List<Integer> smaller = new ArrayList<Integer>();
List<Integer> larger = new ArrayList<Integer>();
List<Integer> same = new ArrayList<Integer>();
Integer integer = items.get(items.size() / 2);
for (Integer temp : items) {
if (temp < integer) {
smaller.add(temp);
} else if (temp > integer) {
larger.add(temp);
} else
same.add(integer);
}
sort(smaller);
sort(larger);
items.clear();
items.addAll(smaller);
items.addAll(same);
items.addAll(larger);
}
}
private static void Print(List<Integer> item) {
for (Integer integer : item) {
System.out.print(integer + " ");
}
System.out.println();
}
}