计算机算法基础:分治法

基本思想:

为解决一个大问题:

  1. 分解成两个或多个更小的问题
  2. 分别解决每个小问题
  3. 把各小问题的解答组合起来,即可得到原问题的解
    小问题通常与原问题相似或同质,因而可以递归地分治。
    同质

分治策略的抽象化控制

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对两个子区间的子结果进行合并的时间

二分检索(折半查找)

  1. 问题描述
    已知一个按非降次序排列的元素表a1, a2, …,an,判定某给定的元素x是否在该表中出现。若是,则找出x在表中的位置并返回其所在下;若非,则返回0值。
  2. 算法设计
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
  1. 算法的正确性证明
  • 在具体指定A中的数据元素及x的数据类型后,算法中的所有运算都能按要求正确运行——即首先满足确定性和能行性
  • 终止性:满足条件结束程序
  1. 性能分析
  • 空间特性:n+5个空间位置——O(n)
  • 时间特性:成功检索/不成功检索

二元比较树

算法执行过程的主体是x与一系列中间元素A(mid)比较。可用一棵二元树描述这一过程,并称之为二元比较树。
内结点(成功,圆形)、外结点(不成功,方形)、路径
若n在区域[2k-1,2k)中,则对于一次成功的检索,BINSRCH至多做k次比较;对于一次不成功的检索,或者做k-1次比较,或者做k次比较。
在这里插入图片描述
任何一种以比较为基础的算法,在最坏情况下的计算时间都不低于Ο(logn)。因此, 不可能存在最坏情况比二分检索数量级还低的算法。
二分检索是解决检索问题的最优的最坏情况算法。

找最大最小元素

  1. 问题描述:
    给定含有n个元素的集合,在其中找出最大和最小元素。
  2. 算法设计:
	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
  1. 比较次数
    最好情况:按递增次序排列,元素比较次数为n-1次
    最坏情况:按递减次序排列,元素比较次数为2(n-1)次
    平均情况:元素比较次数为3(n-1)/2次
  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
  1. 性能分析
    在这里插入图片描述

归并分类

  1. 分类问题:排序
  • 内排序:冒泡,插入,归并,快排,堆排
  • 外排序
  1. 插入分类
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)
  1. 归并分类(分治策略)
	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
发布了21 篇原创文章 · 获赞 0 · 访问量 328

猜你喜欢

转载自blog.csdn.net/weixin_44225940/article/details/104005958
今日推荐