将原问题划分成若干个规模较小而结构与原问题一致的子问题;递归的解决这些子问题,然后在合并其结果,就得到原问题的解
容易确定运行时间,是分治算法的优点之一。
分治模式在每一层都递归上都有三个步骤:
-分解:将原问题分解成一系列的子问题
-解决:递归的解决子问题,若子问题足够小,则直接有解。
-合并:将子问题的结果合并成原问题的解
分治的关键点
-原问题可以一直分解为形式相同的子问题,当子问题规模较小时可以自然求解。
-子问题的解通过合并可以得到原问题的解。
-子问题的分解以及解的合并一定是比较简单的,否者分解和合并所花的时间可能超过暴力解法,得不偿失。
快速排序算法
1.分解:数组A[p..r]被划分为两个子数组A[P..q-1]和A[q+1..r]使得A[q]为大小居中的数,使得左侧A[p..q-1]中的每个元素都小于他,右侧A[q+1..r]中的每一个元素都大于他。其中计算下标 q也是划分的一部分。
2.解决:通过递归调用快速排序,对子数组A[p..q-1],A[q+1..r]进行排序
3.合并:数组A[q..r]已经有序所以不需要排序
划分之一遍单项扫描分区法:
-一遍扫描法的思路是:用两个指针将数组划分为三个区间,
-扫描指针左边是确认小于等于主元的
-末指针右边是用来放大于主元的元素
import java.util.Arrays;
import lanqiao.Swap;
public class QuickSort {
public static void main(String[] args) {
// TODO Auto-generated method stub
//int arr[] = new int[5];
//Swap.ArryRandom(arr, 5);
//System.out.println(Arrays.toString(arr));
int[] brr = new int[]{9,5,6,8,4};
quicksort(brr,0,brr.length-1);
System.out.println(Arrays.toString(brr));
}
public static void quicksort(int[] arr, int start, int end) {
if(start<end) {//递归的出口
int q = partition(arr,start,end);//找到主元数组下标
quicksort(arr,start,q-1);//对左边进行快排,
quicksort(arr,q+1,end);//对右边进行快排
}
}
//找主元
public static int partition(int arr[],int start,int end) {
int zuyuan = arr[start];//主元初始化
int sp = start+1;//左侧扫描指针
int bigger = end;//右侧末指针
//两个指针交错说明数组已经扫描完了
while(sp<=bigger) {
if(arr[sp]<=zuyuan) {//扫描指针所指元素比主元小或者相等
sp++;
}
else {//扫描指针所指元素比主元大
Swap.swap(arr,sp,bigger);
bigger--;
}
}
Swap.swap(arr, start, bigger);//把主元放到bigger这个位置,这样bigger左边都小于主元,右边都大于主元
return bigger;
}
}