基本思想:
为解决一个大问题:
- 分解成两个或多个更小的问题
- 分别解决每个小问题
- 把各小问题的解答组合起来,即可得到原问题的解
小问题通常与原问题相似或同质,因而可以递归地分治。
分治策略的抽象化控制
procedure DANDC(p,q)
global n,A(1:n);
integer m,p,q;//1<=p<=q<=n
if SMALL(p,q)
then return(G(p,q))
else
m<-DIVIDE(p,q)//p<=m<=q return(COMBINE(DANDC(p,m),DANDC(m+1,q)))
endif
end DANDC
分析
- k=2:二分是最常用的分解策略;
- SMALL(p,q):布尔函数,判断输入规模q-p+1是否足够小而无需进一步分解
- G(p,q):对输入规模为q-p+1的子问题求解
- DIVIDE(p,q):对输入规模为q-p+1的i问题进一步分解,返回值为[p.q]区间进一步的分割点
- COMBINE(x,y):子结果的合并函数,将区间[p,m]和[m+1,q]上的子问题的解合并成上级区间[p,q]上的较完整解。当p=1,q=n时,就得到整个问题的解。
DANDC的计算时间
若两个子问题的输入规模大致相当,则DANDC总的计算时间可用递归关系式表示:
T(n)=g(n),n足够小
2T(n/2)+f(n),否则
注:
- T(n):表示输入规模为n的计算时间
- g(n):表示对足够小的输入规模直接
- f(n):表示COMBINE对两个子区间的子结果进行合并的时间
二分检索(折半查找)
- 问题描述
已知一个按非降次序排列的元素表a1, a2, …,an,判定某给定的元素x是否在该表中出现。若是,则找出x在表中的位置并返回其所在下;若非,则返回0值。 - 算法设计
procedure BINSRCH(A,n,x,j)//A为降次排列的数组
integer low,high,mid,j,n;
low<-1;high<-n;
while low<=high do
mid<-(low+high)/2
case
:x<A(mid):high<-mid-1
:x>A(mid):low<-mid+1
:else:j<-mid;return
endcase
repeat
j<-0
end BINSRCH
- 算法的正确性证明
- 在具体指定A中的数据元素及x的数据类型后,算法中的所有运算都能按要求正确运行——即首先满足确定性和能行性
- 终止性:满足条件结束程序
- 性能分析
- 空间特性:n+5个空间位置——O(n)
- 时间特性:成功检索/不成功检索
二元比较树
算法执行过程的主体是x与一系列中间元素A(mid)比较。可用一棵二元树描述这一过程,并称之为二元比较树。
内结点(成功,圆形)、外结点(不成功,方形)、路径
若n在区域[2k-1,2k)中,则对于一次成功的检索,BINSRCH至多做k次比较;对于一次不成功的检索,或者做k-1次比较,或者做k次比较。
任何一种以比较为基础的算法,在最坏情况下的计算时间都不低于Ο(logn)。因此, 不可能存在最坏情况比二分检索数量级还低的算法。
二分检索是解决检索问题的最优的最坏情况算法。
找最大最小元素
- 问题描述:
给定含有n个元素的集合,在其中找出最大和最小元素。 - 算法设计:
procedureAIATMIN(A,n,max,min)//将A中最大值置于max,最小值置于min
Integer i,n
max<-min<-A(1)
for i<-2 to n do
if A(i)>max then
max<-A(i)
endif
if A(i)<min then
min<-A(i)
endif
repeat
end STRAITMAXMIN
- 比较次数
最好情况:按递增次序排列,元素比较次数为n-1次
最坏情况:按递减次序排列,元素比较次数为2(n-1)次
平均情况:元素比较次数为3(n-1)/2次 - 分治法求解策略
MAX(I) = max(MAX(I1),MAX(I2))
MIN(I) = min(MIN(I1),MIN(I2))
递归求解:
procedure MAXMIN(i,j,fmax,fmin)
integer i,j;global n,A(1:n)
case
:i=j:fmax<-fmin<-A(i)
:i=j-1:if A(i)<A(j) then fmax<-A(j):fmin<-A(i)
endif
:else:mid<-(i+j)/2
call MAXMIN(i,mid,gmax,gmin)
call MAXMIN(mid+1,j,hmax,hmin)
fmax<-max(gmax,hmax);fmin<-min(gmin,gmin)
end case
end MAXMIN
- 性能分析
归并分类
- 分类问题:排序
- 内排序:冒泡,插入,归并,快排,堆排
- 外排序
- 插入分类
procedure INSERTIONSORT(A,n)
A(0)<- -∞
for j<-2 to n do
item<-A(j);i<-j-1
while item<A(i) do
A(i+1)<-A(i);i<-i-1
repeat
A(i+1)<-item;
repeat
end INSERTIONSORT
性能分析
- 最坏情况:O(n2)
- 最好情况:O(n)
- 归并分类(分治策略)
procedure MERGESORT(low,high)
integer low,high
if low<high then
mid<-(low+high)/2
call MERGESORT(low,mid)
call MERGESORT(mid+1,high)
call MERGE(low,mid,high)
endif
end MERGESORT
procedure MERGE(low,mid,high)
//A(low,high)是一个全程数组,它含有两个放在A(low,mid)和A(mid+1,high)中的已分类子集合,目标是将这两个已分类的集合归并成一个集合,并存放到A(low,high)中
integer h,l,j,k,low,mid,high;
global A(low,high);local B(low,high)
h<-low;i<-low;j<-mid+1;
while h<=mid and j<=high do//当两个集合都没有取尽时,将较小的元素先存放到B中
if A(h)<=A(j) then B(i)<-A(h);h<-h+1//如果前一个数组中的元素较小
else B(i)<-A(j);j<-j+1//如果后一个数组中的元素较小
endif
repeat
//处理尚有剩余元素的集合
if h>mid then for k<-j to high do B(i)<-A(k);i<-i+1;repeat
else for k<-h to mid do B(i)<-A(k);i<-i+1;repeat
endif
for k<-low to high do A(k)<-B(k) repeat//将已归并的集合复制到A中
end MERGE
性能分析:
T(n)=O(nlogn)
4. 快速分类
划分过程:
procedure PARTITION(m,p)
integer m,p,i; global A(m:p-1)
v<-A(m);i<-m//A(m)是划分元素
loop
loop i<-i+1 until A(i)>=v repeat//i由左向右移
loop p<-p-1 until A(
end PARTITION