分治法
文章目录
一、一般方法
分治法的三个步骤:
- 分解(Divide,分):将问题划分为一些子问题,子问题的形式与原问题一样,只是规模更小;
- 解决(conquer,治):递归求解出子问题。如果子问题的规模足够小,则停止递归,直接求解;
- 合并(combine,合):将子问题的解组合成原问题的解。
二、分治法的应用——二分检索(折半查找、BINSRCH)
二分检索——是采用分治法来解决有序表的排列问题。
问题描述:
- 已知一个按非降序排列的元素表
a 1 ≤ a 2 ≤ … ≤ a n a_1≤a_2 ≤ … ≤ a_n a1≤a2≤…≤an- 给定元素x
判断x是否在该表中出现- 若是, 则找出该元素在表中的位置,并将下标值赋给j
否则置j为0
二分检索原理:
- 将二分检索问题表示为: I = ( n , a 1 , … , a n , x ) I=(n, a_1, … , a_n, x) I=(n,a1,…,an,x)
即从包含n个元素的非降序排列元素表中检索元素 x x x- 选取一个下标k,可得到三个子问题:
I 1 = ( k − 1 , a 1 , … , a k − 1 , x ) I_1=(k-1, a_1, … , a_{k-1}, x) I1=(k−1,a1,…,ak−1,x)
I 2 = ( 1 , a k , x ) I_2=(1, a_k , x) I2=(1,ak,x)
I 3 = ( n − k , a k + 1 , … , a n , x ) I_3=(n-k, a_{k+1}, … , a_n, x) I3=(n−k,ak+1,…,an,x)- 对所求解的问题(或子问题)所选的下标都是
中间元素的下标, k = ⌊ ( n + 1 ) / 2 ⌋ k= \left\lfloor(n+1)/2\right\rfloor k=⌊(n+1)/2⌋
二分检索算法(伪代码描述):
二分检索实例:
设在A(1:9)中顺序放了一下九个元素:
二分检索算法所需的空间与时间
1.所需空间:
- 用n个位置存放数组A
- 还有low, high, mid, x, j五个变量需要存储
共需空间 n+5
2.所需时间:
对于计算时间,我们需要考虑一下情况:
- 成功检索的最好情况、平均情况、最坏情况
- 不成功检索的最好情况、平均情况、最坏情况
成功检索一共有n种情况,不成功检索有n+1种情况
例如在上面的实例中,成功检索的情况有9种,不成功的有10种。
成功检索的三种情况(即在数组A中找到x):
- 最好情况:用最少的比较找到x的情况。
- 最坏情况:用最多的比较找到x情况。
- 平均情况:成功情况中的所有情况都考虑。
同理,不成功检索也有三种情况。
针对上面的实例,我们利用二分检索对应的二元比较树来计算所需的时间。
该二元比较树有9个内节点,由 2 3 ≦ 9 ≦ 2 4 2^3\leqq\ 9 \leqq\ 2^4 23≦ 9≦ 24,树的高度为4。
由二分检索对应的二元比较树可知,
- 成功检索的最好情况比较1次。
成功检索的最坏情况比较4次。
成功检索的平均情况为 3 + 2 + 3 + 4 + 1 + 3 + 2 + 3 + 4 9 = 2.7777 … … \frac{3+2+3+4+1+3+2+3+4}{9}=2.7777…… 93+2+3+4+1+3+2+3+4=2.7777……次- 不成功检索的最好情况比较3次。
不成功检索的最坏情况比较4次。
不成功检索的平均情况为 3 + 3 + 3 + 4 + 4 + 3 + 3 + 3 + 4 + 4 10 = 3.4 \frac{3+3+3+4+4+3+3+3+4+4}{10}=3.4 103+3+3+4+4+3+3+3+4+4=3.4次
于是二分检索BINSRCH算法的时间复杂度为:
另一种算法的实现:
对于之前给出的算法,while循环中的代码块如下:
在BINSRCH程序的While循环中,case语句可能要做两次比较;
于是我们给出每次循环固定比较一次的二分检索算法。
实例分析:
三、分治法的应用——归并排序(合并排序、MERGESORT)
问题描述:
给定一个含有n个元素的集合,对其进行排序(如非降次序)
归并排序的基本思想:
(1)将待排序元素分成大致相同的两个子集合
(2)分别对两个子集合进行排序
(3)将排好序的两个子集合并成一个排好序的集合
归并排序的算法伪代码描述:
归并排序的执行过程:
归并排序的计算时间:
考虑Merge算法,合并两个数组所需的比较次数。
假设两个数组长度都为k,总长度为n,最好情况下比较 k k k (也就是 n 2 \frac {n} {2} 2n) 次,最坏情况下比较 2 k + 1 2k+1 2k+1(也就是 n − 1 n-1 n−1)次。
因此归并排序的计算时间:
当 n = 2 k n=2^k n=2k时,可得
T ( n ) = 2 ( 2 T ( n 4 ) + c n 2 ) + c n = 2 2 T ( n 4 ) + 2 c n = 2 2 ( 2 T ( n 8 ) + c n 4 ) + 2 c n = 2 3 T ( n 8 ) + 3 c n … … = 2 k T ( 1 ) + k c n = a n + c n l o g n T(n)=2(2T(\frac {n}{4})+c\frac{n}{2})+cn\\ \qquad = 2^2T(\frac{n}{4})+2cn\\ \qquad = 2^2(2T(\frac{n}{8})+c\frac{n}{4})+2cn\\ \qquad = 2^3T(\frac{n}{8})+3cn\\ \qquad ……\\ \qquad = 2^kT(1)+kcn\\ \qquad = an+cnlogn T(n)=2(2T(4n)+c2n)+cn=22T(4n)+2cn=22(2T(8n)+c4n)+2cn=23T(8n)+3cn……=2kT(1)+kcn=an+cnlogn
最终得到 T ( n ) = O ( n l o g n ) T(n)=\Omicron(nlogn) T(n)=O(nlogn)