第5章 分治法

分治法

将规模为N的问题分解为k个规模较小的子问题,使这些子问题相互独立可分别求解,再将k个子问题的解合并成原问题的解.如子问题的规模仍很大,则反复分解直到问题小到可直接求解为止。
在分治法中,子问题的解法通常与原问题相同,自然导致递归过程。

特点:
算法适宜并行计算
算法的计算复杂度对应如此递归方程 T(n)=aT(n/b)+f(n)

  • T(n)=aT(n/b)+f(n)递推式的解法

合并排序

  • 算法思想:若n为1,算法终止;
    否则,将n个待排元素分割成k(k=2)个大致相等子集合A、B,对每一个子集合分别递归排序,
    再将排好序的子集归并为一个集合。

  • 合并:
    前提:数组B及数组C已经有序。
    比较数组B的第一个记录与数组C的第一个记录将KEY值小者输出至数组A,再从相应数组读进一个记录,替代已被输出的记录,再继续比较。
    结束:直至有一个数组的记录已被穷尽,然后再将未穷尽的数组上的所有记录拷贝到输出数组A上。
    C(n) = 2C(n/2)+Cmerge(n)
    最坏情况:
    归并过程的最坏复杂度为 Cmerge(n)=n-1,
    排序算法的最坏复杂度为
    C (n)=2C(n/2)+n-1
    解得C(n)=nlog2n-n+1∈Θ(nlog2n)

  • 合并排序总结:
    最坏情况Θ(nlog2n)
    优点:
    1.合并排序在最坏情况下的键值比较次数十分接近于任何基于比较的排序算法在理论上能够达到的最少次数
    2.合并排序精确解Cworst(n)=nlog2n-n+1
    3.理论最小值nlog2n-1.44n向上取整
    缺点:
    1.需要线性的额外空间
    2.虽然合并也可做到“在位”,但导致算法过于复杂

给予合并排序思想找出n个元素中第k个最小元素:
将n个元素分为每段有k个元素的有序段,两个k元素有序段合并成一个k元素有序段,递归此过程。

快速排序

  • 算法思路:
    对于输入A[0.. n-1],按以下三个步骤进行排序:
    1.分区:取A中的一个元素为支点(pivot) 将A[0..n-1]划分成3段: A[0..s-1], A[s ], A[s+1..n-1], 使得
    A[0..s-1]中任一元素<=A[s],
    A[s+1..n-1]中任一元素>=A[s]; 下标s 在划分过程中确定。
    2.递归求解:递归调用快速排序法分别对A[0..s-1]和A[s+1..n-1]排序。
    3.合并:合并A[0..s-1], A[s], A[s+1..n-1]为A[0..n-1]
  • 整个算法的最坏情况下:
    在进行了n+1次比较后建立了分区,还会对数组进行排序, 继续到最后一个子数组A[n-2..n-1]。总比较次数为:
    Cworst(n)=(n+1)+n+…+3
    =(n+2)(n+1)/2-3
    ∈Θ(n2)
  • 最好情况
    每次分区执行n次
    并且每次都是等分
    Cbest(n)=2Cbest(n/2)+n
    ∈Θ(nlog2n)
  • 平均情况
    分裂点有可能在一次分区后出现在每个位置
    设概率是1/n


    图片1.png

基于快排思想找第k个最小元素
算法思想:
1.任选一个元素为支点a
2.将集合中的元素划分成S1与S2,其中S1={x|xa}
3.依据S1与S2大小确定第k个最小元素所在的集合,不妨设为S1
4.在S1上递归应用以上思想直到第k个最小元素被找出
复杂度:
最坏情况下 T(n)=T(n-1)+O(n)
并且当k约等于n/2时,T(n)为O(n2)
平均情况下 每次递归均在n/2的子表上进行,即复杂度满足 T(n)=T(n/2)+O(n) 即T(n)=O(n)。

二叉树的遍历及其相关特性

所谓二叉树的遍历指的是遵循某一种次序来访问二叉树上的所有结点,使得树中每一个结点被访问了一次且只访问一次。
由于二叉树是一种非线性结构,树中的结点可能有不止一个的直接后继结点,所以遍历以前必须先规定访问的次序。

  • 中序遍历
    二叉树的中序遍历算法比较简单,使用递归的策略。在遍历以前首先确定遍历的树是否为空,如果为空,则直接返回;否则中序遍历的算法步骤如下:
    (1)对左子树L执行中序遍历算法
    (2)访问输出根结点V的值。
    (3)对右子树R执行中序遍历算法。
  • 先序遍历
    有了上面的中序遍历的过程,前序遍历也是类似的。在遍历以前首先确定遍历的树是否为空,如果为空,则直接返回;否则前序遍历的算法步骤如下:
    (1)访问输出根结点V的值;
    (2)对左子树L执行前序遍历算法。
    (3)对右子树R执行前序遍历算法。

大整数乘法

分治法如何体现。
令N为偶数,则A和B可表示为
其中a1和a2分别为A的前半部和后半部。
A=a1·10N/2+a2 (123456=123·106/2+456)
B=b1·10N/2+b2
b1和b2则分别为B的前半部和后半部。如果按下述方法得到积(多项式相乘)
A·B=(a110n/2+a2)(b110n/2+b2)
=a1b110n+(a1b2+a2b1)10n/2+a2b2

要4次N/2位乘法,即N2次一位乘法。因此这种方法没有改进原来的方法。
T(n) = 4 T(n/2) + O(n) ------------ O(n2)

改进:
(a1+a2)(b1+b2) = a1b1 + a1b2 + a2b1 + a2b2
若认定 a1b1 与 a2b2 为必须计算的,则
a1b2 + a2b1 = (a1+a2)(b1+b2) - a1b1- a2b2
左边的两次乘法, 转换成 右边的 3 次乘法!

这种方法需要3次n/2位的乘法及一些加减法。
记C(n)为计算两个n位整数相乘所需的基本操作(1位数的乘法或加法)执行次数,则
有 C(n)=3C(n/2)+k·n
C(1)=1
其中,k为常数, k·n表示加法、减法所需时间与n成正比。 解此递归方程 得
C(n)=nlog3+2knlog3-2kn
所以 C(n)∈O(nlog3) ≈ O(n1.58)

Strassen矩阵乘法

普通矩阵分治法
将矩阵A,B和C中每一矩阵都分块成为4个大小相等的子矩阵,每个子矩阵都是n/2×n/2的方阵。由此可将方程C=A×B重写为:
C11=A11B11+A12B21
C12=A11B12+A12B22
C21=A21B11+A22B21
C22=A21B12+A22B22
计算2个n阶方阵的乘积转化
为计算8个n/2阶方阵的乘积和4个n/2阶方阵的加法
T(n)=8T(n/2)+cn2
T(1)=1
解仍然属于O(n3)

Strassen矩阵乘法
M1=A11(B12 - B22)
M2=(A11+A12)B22
M3=(A21+A22)B11
M4=A22(B21-B11)
M5=(A11+A22)(B11+B22)
M6=(A12-A22)(B21+B22)
M7=(A11-A21)(B11+B12)
算法只用了7次乘法运算,但增加了加、减法的运算次数10次。
C11=M5+M4-M2+M6
C12=M1+M2
C21=M3+M4
C22=M5+M1-M3-M7
用了7次对于n/2阶矩阵乘积的递归调用和18次n/2阶矩阵的加减运算。
T(n)=7T(n/2)+kn2
T(1)=1
解为T(n)∈O(nlog7)≈O(n2.81)。

最近点对问题

先将x1,x2,..,xn排好序,
然后,用一次线性扫描就可以找出最接近点对。
这种方法计算时间主要花在排序上,在排序算法中已经证明,时间复杂度为O(nlogn)。
然而这种方法无法直接推广到二维的情形。

对这种一维的简单情形,我们还是尝试用分治法来求解,并希望能推广到二维的情形。
假设我们用x轴上某个点m将S划分为2个子集S1和S2,
使得S1={x∈S|x≤m}; S2={x∈S|x>m}。


图片4.jpg

递归地在S1和S2上找出其最接近点对{p1,p2}和{q1,q2},并设d=min{|p1-p2|,|q1-q2|},S中的最近点对 或者是{p1,p2},或者是{q1,q2},或者是某个{p3,q3},其中p3∈S1且q3∈S2, |S1|=k, |S2|=n-k。


图片3.jpg

注意:如果{p3,q3}是最近点对, p3,q3 一定都在[m-d, m+d]中
随意划分: T(n) = T(k)+T(n-k) +O(n)
其中O(n) 为划分成两个子集的开销

该算法的分割步骤和合并步骤总共耗时O(n)。
因此,理想状态下, 找到中位元素进行划分
算法耗费的计算时间T(n)满足的递归方程为:


图片2.png

解得T(n)=O(nlog n)
前提是平衡点划分!
二维:


图片5.png

递推式
T(n) = 2T(n/2) + O(n)
得到T(n)属于O(nlog n)。

凸包问题

1 将点按x轴升序排列
2 找出最左点Pi和最右点Pj
(对应于图例中的P3 ,P6, 它们一定是该集合的凸包顶点)
3 Pi到Pj 的直线将凸包分成上/下包
4 递归地构造上包与下包
5.递归构造上包:
寻找距离直线 P1Pn 的左侧最远点Pmax
Pmax是凸包上的顶点
P1PmaxPn形成4个区域,顶点在四个区域外离边界距离最远
用同样的方法处理上包中的2个区域S1与S2


6.PNG

算法的复杂度为:
1.排序: O(n log n)
2.递归构造上包与下包 , 类同于快速排序
T(n)=2T(n/2)+O(n)----平均O(n log n)
T(n)=T(n-1)+O(n)----最坏O(n^2)

你可能感兴趣的:(第5章 分治法)