递归与分治法1

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。


解题思路
Fn 1 Fn 2 Fn 1 n 3; n 1,2.
递归程序实现 F(n) if n<=1 then return 1 else return F(n-1)+F(n-2) 非递归程序实现 F(n) F0 ← 1 F1 ← 1 for i ← 1 to n do F2 ← F1+F0 F0 ← F1 F1 ← F2 return F2

Hanoi塔问题

问题描述 有n个圆盘,半径各不相同,依半径从大到小 自下而上套在A柱上,另还有B、C两根空柱, 现要求将A柱上的n个圆盘全部搬到C柱上去且 每次只许搬动一个盘子,还必须始终保持每根 柱子上是小盘在上,大盘在下。试问: (1)要移动多少次才能把A柱上的n个圆盘移到 C柱上? (2)怎么个移动法?
程序的实现
Perm(r, k, m) if k=m then for i ← 0 to m do output r[i] else for i ← k to m do exchange r[k] ↔ r[i] Perm(r, k+1, m) exchange r[k] ↔ r[i]
分治法
算法思想 分而治之方法与软件设计的模块化方法非常相 似。为了解决一个大的问题,可以: 1) 把它分成两个或多个更小的问题; 2) 分别解决每个小问题; 3) 把各小问题的解答组合起来,即可得到原问 题的解答。 小问题通常与原问题相似,可以递归地使用分 而治之策略来解决。


算法描述 将2k×2k 棋盘分为如图e)所示的4个2k-1×2k-1棋 盘。注意到当完成这种划分后, 4个小棋盘中 仅仅有一个棋盘存在残缺方格(因为原来的 2k×2k棋盘仅仅有一个残缺方格)。首先覆盖 其中包含残缺方格的2k-1×2k-1残缺棋盘,然后 把剩下的3个小棋盘转变为残缺棋盘,为此将 一个三格板放在由这3个小棋盘形成的角上, 如图f) 所示。采用这种分割技术递归地覆盖 2k×2k残缺棋盘直至棋盘的大小减为1×1时, 递归过程终止。

QuickSort(A,p,r) if p < r then q← Partition(A, p, r) QuickSort(A, p, q - 1) QuickSort(A, q + 1, r) QuickSort(A, 1, length[A])
划分程序
Partition(A, p, r) x ← A[r] i←p-1 for j ← p to r - 1 do if A[j] ≤ x then i ← i + 1 exchange A[i] ↔ A[j] exchange A[i + 1] ↔ A[r] return i + 1

考虑n=3的情况

n=4的一个解
ChessMove(n) if n=4 then MovetoSpace(4) MovetoSpace(8) MovetoSpace(2) MovetoSpace(7) MovetoSpace(4) else MovetoSpace(n) MovetoSpace(2n-1) ChessMove(n-1)

sum(x) j ← j+1 for k ← 1 to x-1 do output a[k] output a[x] k ← x; p ← a[k] for m ← a[k-1] to (p div 2) do a[k] ← m; a[k+1] ←p-m; sum(k+1) main() j←0 if n>=2 then for i ← 1 to (n div 2) do a[1] ← i; a[2] ← n-a[1]; sum(2)
例子
残缺棋盘问题
残缺棋盘是一个有2k×2k 个方格的棋盘,其中 恰有一个方格残缺。残缺棋盘的问题要求用L 型的格板覆盖残缺棋盘。在此覆盖中,两个三 格板不能重叠,三格板不能覆盖残缺方格,但 必须覆盖其他所有的方格。 图中给出k≤2时各种可能的残缺棋盘,其中残 缺的方格用阴影表示。注意当k= 0时,仅存在 一种可能的残缺棋盘。事实上,对于任意k, 恰好存在22k 种不同的残缺棋盘。
递归策略
递归算法:一个直接或间接的调用自身的 算法。它通常把一个大型复杂的问题层层 转化为一个与原问题相似的规模较小的问 题来求解,递归策略只需少量的程序就可 描述出解题过程所需要的多次重复计算, 大大地减少了程序的代码量。 递归程序:递归函数,递归过程 注意: (1) 递归就是在过程或函数里调用自身; (2) 在使用递增归策略时,必须有一个明 确的递归结束条件,称为递归出口。

递归的应用

阶乘函数
n (n 1)! n 1; n! 1 n 0.
程序的实现 Factorial(n) if n=0 then return 1 else return n*Factorial(n-1)

Fibonacci数列

Fibonacci兔子问题描述 从某天开始把雄和雌各一的一对兔子放入养殖 场中,小兔经过一个月长大。长大后,每个月 它们都繁殖一对雄和雌各一的一对小兔,每对 新兔经过一个月长大。长大后,每对新兔也繁 殖一对雄和雌各一的一对小兔,如果每一对兔 子的繁殖按上面所说的方式,试问第n个月, 养殖场中有多少对兔子呢?
随机快速排序(改进)
RandomizedPartition(A,p,r) i← Random(p,r) exchange A[p]↔A[i] return Partition(A,p,r)
归并排序问题
该问题是将n 个元素排成非递减顺序。 算法描述 若n为1,算法终止;否则,将这一元素 集合分割成两个或更多个子集合,对每 一个子集合分别排序,然后将排好序的 子集合归并为一个集合。
伪币问题的推广:二分搜索
问题描述 给定已经排好序的n个元素a[0..n-1],现要从 这n个元素中找出一特定元素。 求解思路 二分搜索算法的基本思想是将n个元素分成个 数大致相同的两半,取a[n/2]与x进行比较。 如果x=a[n/2]则找到x,算法中止。如果 x<a[n/2],则只要在数组a的左半部分继续搜 索x。如果x>a[n/2],则只需继续搜索数组a的 右半部分。
TileBoard(tr, tc, dr, dc, size) if size = 1 return t ← tile++ s ← size/2 if dr < tr + s and dc < tc + s then TileBoard ( t r, tc, dr, dc, s) else Board[tr + s - 1][tc + s - 1] ← t TileBoard ( t r, tc, tr+s-1, tc+s-1, s) if dr < tr + s and dc >= tc + s then TileBoard ( t r, tc+s, dr, dc, s) else Board[tr + s - 1][tc + s] ← t TileBoard ( t r, tc+s, tr+s-1, tc+s, s)
MovetoSpace(k) c[sp] ← c[k] c[k] ←空格 c[sp+1] ← c[k+1] c[k+1] ←空格 sp ←k
自然数的拆分问题
问题描述 任何一个大于1的自然数n,总可以拆分成若干 个小于n的自然数之和。给定n,求n的所有拆 分。 例如n=4,可拆分为 4=1+3 4=1+1+2 4=1+1+1+1 4=2+2 解题思路
快速排序问题
该问题是将n 个元素排成非递减顺序。 解题思路 分解:将输入的序列A[p..r]划分成两个非空 子序列A[p..q-1]和A[q+1..r]。 递归求解:通过递归调用快速排序算法分别对 A[p..q-1]和A[q+1..r]进行排序。 合并:将从小到大已排序的A[p..q-1]和 A[q+1..r]合并使其按从小到大排序
Hale Waihona Puke Baidu 棋子移动问题

问题描述 有2n个棋子(n>3)排成一行,开始时白子 全部在左边,黑子全部在右边,要求把它 移成黑白相间的一行棋子。 移动规则: 每次必须移动相邻的2个棋子,颜色不限; 但是不能调换2个棋子的左右位臵。移动 必须跳过若干个棋子到左边或右边的空位 上去(不能平移)。
解题思路

考虑n=5的情况
Hanoi(n, A, B, C) if n=1 then move(1, A, C) else Hanoi(n-1, A, C, B) move(n, A, C) Hanoi(n-1, B, A, C)
排列问题

排列问题 设R={r1,r2,…,rn}是要进行排列的n个元 素,Ri =R-{ri }。集合R中元素的全排列 记为Perm(R)。 (ri)Perm(Ri)表示在全排 列Perm(Ri)的每一个排列前加上前缀ri得 到的排列。R的全排列可归纳定义如下: 当n=1时, Perm(R)=r1 当n>1时, Perm(R)由(r1)Perm(R1), (r2)Perm(R2),…,(rn)Perm(Rn)构成。

程序实现
BinarySearch(x,a,n) left ← 0 right ← n-1 while left<=right do middle ←(left+right)/2 if x=a[middle] then return middle if x>a[middle] then left ← middle+1 else right ← middle-1 return -1
if dr >= tr + s and dc < tc + s then TileBoard(tr+s, tc, dr, dc, s) else Board[tr + s][tc + s - 1] ← t TileBoard(tr+s, tc, tr+s, tc+s-1, s) if dr >= tr + s and dc >= tc + s then TileBoard(tr+s, tc+s, dr, dc, s) else Board[tr + s][tc + s] ← t TileBoard(tr+s, tc+s, tr+s, tc+s, s)

找伪币问题

给你一个装有16个硬币的袋子。16个硬 币中有一个是伪造的,并且那个伪造的 硬币比真的硬币要轻一些。你的任务是 找出这个伪造的硬币。为了帮助你完成 这一任务,将提供一台可用来比较两组 硬币重量的仪器,利用这台仪器,可以 知道两组硬币的重量是否相同。

算法描述 1)将16个硬币分成A、B两半; 2)将A放仪器的一边,B放另一边,如果A 袋轻,则表明伪币在A,解子问题A即可, 否则,解子问题B。
青蛙过河问题

问题描述
大小各不相同的一队青蛙站在河左岸的石墩 (记为A)上,要过到对岸的石墩(记为D)上 去。河心有几片荷叶(分别设为Y1 … Ym)和几 个石墩(分别设为S1 … Sn)。如下图

青蛙的站队和移动的方法规则如下: 1.每只青蛙只能站在荷叶、石墩或者比它大 一号的青蛙背上; 2.一只青蛙只有在背上没有其他青蛙时才能 从一个落脚点跳到另一个落脚点; 3.青蛙允许从A直接跳到河心的石墩、荷叶 和D上,允许从河心的石墩、荷叶跳到D上; 4.青蛙可以在河心的石墩、荷叶之间以及石 墩和荷叶之间来回跳动; 5.青蛙离开A后,到达D后,均不能再跳回。

MergeSort(A,p,r) if p < r then q← (p + r)/2 MergeSort(A,p,q) MergeSort(A, q + 1, r) Merge(A,p,q,r)
Merge(A, p, q, r) n1←q-p+1 n2←r - q create arrays L[1.. n1 + 1] and R[1 n2 + 1] for i←1 to n1 do L[i]←A[p+i-1] for j←1 to n2 do R[j]←A[q + j] L[n1+1]←∞ R[n2 + 1]←∞ i←1; j←1 for k ← p to r do if L[i] ≤ R[j] then A[k] ← L[i] i←i+1 else A[k] ← R[j] j←j+1
相关文档
最新文档