递归与分治算法 的经典教程!(金英老师)
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
例:用分治法实现快速排序。 用分治法实现快速排序。 (1) 算法设计
对于输入的子数组a[p r], 对于输入的子数组a[p : r],按以下三个步骤进行 排序: 排序:
1. 分解(Divide) 分解(Divide)
以a[p]为基准元素将a[p:r]划分成3段: a[p]为基准元素将 为基准元素将a[p:r]划分成 划分成3 a[p:qa[p:q-1], a[q], a[q+1:r] 使得: 使得: a[p:q-1]中的任何一个元素小于等于 a[p:q-1]中的任何一个元素小于等于a[q]; 中的任何一个元素小于等于a[q]; a[q+1:r]中的任何一个元素大于等于 a[q+1:r]中的任何一个元素大于等于a[q]。 中的任何一个元素大于等于a[q]。
当n<c, T(n) = θ(1). 划分(Divide)阶段的时间复杂性: 划分(Divide)阶段的时间复杂性: 划分问题为a个子问题,每个子问题大小为1/b, 划分问题为a个子问题,每个子问题大小为1/b, 划分时间D(n)可直接得到 可直接得到。 划分时间D(n)可直接得到。 递归求解(Conquer)阶段的时间复杂性: 递归求解(Conquer)阶段的时间复杂性: aT(n/b) 合并(Combine)阶段的时间复杂性: C(n) 合并(Combine)阶段的时间复杂性:
(Strassen’s algorithm for matrix multiplication) )
(一)算法设计
输入:两个n*n矩阵 和 输入:两个n*n矩阵X和Y n*n矩阵 输出: 和 的乘积 输出:X和Y的乘积 通常,计算X*Y的时间复杂性为 的时间复杂性为O(n3), 通常,计算 的时间复杂性为 现给出一个复杂性为O(n2.81)的算法。 的算法。 现给出一个复杂性为 的算法
T(n)=O(logn)。 。
9
n=0 n>0
求解递归方程解的渐进解得:
第4节 大整数的乘法
(一)算法设计 输入: 位二进制整数 位二进制整数X和 输入:n位二进制整数 和Y 输出: 和 的乘积 输出:X和Y的乘积 将每两个一位数的乘法或加法看作一步运算。 将每两个一位数的乘法或加法看作一步运算。 通常, 通常,计算X*Y的时间复杂性为O(n2), 现给出一个复杂性为O(n1. 59)的算法。
8
时间复杂性分析
分解( 分解(Divide)阶段所花时间: )阶段所花时间: O(1) T(n/2) 递归求解( 递归求解(Conquer)阶段所花时间: )阶段所花时间: 合并( 合并(Combine)阶段所花时间: )阶段所花时间: O(1)
时间复杂性递归方程:
θ(1) T(n) = T(n/2)+ θ(1)
第二章 递归与分治
第1节 递归的概念
递归函数:一个使用函数自身给出定义的函数。 递归函数:一个使用函数自身给出定义的函数。 递归算法:一个直接或间接调用自身的算法。 递归算法:一个直接或间接调用自身的算法。 在计算机算法设计与分析中,使用递归技术往往使 在计算机算法设计与分析中, 函数的定义和算法的描述简洁且易于理解。 函数的定义和算法的描述简洁且易于理解。 有些数据结构如二叉树等, 有些数据结构如二叉树等,由于其本身固有的递归 特别适合用递归的形式来描述。还有一些问题, 性,特别适合用递归的形式来描述。还有一些问题, 虽然其自身没有明显的递归结构, 虽然其自身没有明显的递归结构,但用递归技术来求 解使设计出的算法简洁易懂且容易分析。 解使设计出的算法简洁易懂且容易分析。
Template <class Type> void MergeSort (Type a[ ], int left, int right) { if (left<right)
//至少有两个元素 //至少有两个元素 {int i=(left+right)/2; //取中点 //取中点 ( )
MergeSort(a, left, i); ( ) MergeSort(a, i+1, right); ) ( Merge(a, b, left, right); //将两个有序子段和并 //将两个有序子段和并 Copy(a, b, left, right); //从数组b复制到数组a //从数组 复制到数组a 从数组b }
(二)算法复杂性分析 建立递归方程: 建立递归方程:
θ(1) T(n) = 3(T/2) + θ(n)
当n = 1 当n > 1
Байду номын сангаас1.59
用套用公式法求此递归方程解的渐进阶得: 用套用公式法求此递归方程解的渐进阶得:
T(n) = θ(n
log 2 3
) = θ(n
)
11
第5节 Strassen矩阵乘法 Strassen矩阵乘法
2
第2节 分治法(Divide-and-Conquer) 分治法(Divide-and-Conquer) 的基本思想
(一)分治算法的设计 一 分治算法的设计
分治算法的设计过程分为三个阶段: 分治算法的设计过程分为三个阶段: • 分解(Divide)阶段: 分解(Divide)阶段 阶段: 将整个问题划分为多个子问题; 将整个问题划分为多个子问题; • 递归求解(Conquer)阶段: 递归求解(Conquer)阶段: (递归调用正在设计的算法)求解每个子问题; 递归调用正在设计的算法)求解每个子问题; • 合并(Combine)阶段: 合并(Combine)阶段: 合并子问题的解,形成原始问题的解。 合并子问题的解,形成原始问题的解。
C11 C12 C C 22 21
=
A11 A 21
A12 A22
B11 B 21
B12 B22
由此可得: 由此可得
C11= A11 B11 + A12 B21 C12= A11 B12 + A12 B22 C21= A21 B11 + A22 B21 C22= A21 B12 + A22 B22
X=
n/2位 n/2位 位 位 A B
Y=
n/2位 n/2位 位 位 C D
XY = (A2n/2 + B)(C2n/2 + D) = AC2n + (AD + BC)2n/2 + BD = AC2n + ((A − B)(D − C) + AC + BD)2n/2 + BD
10
算法: 算法:
计算A-B和D-C; 和 计算 计算n/2位乘法 、BD、(A-B)(C-D); 计算 位乘法AC、 、 位乘法 计算(A-B)(C-D)+AC+BD; 计算 AC左移 位,((A-B)(C-D)+AC+BD)左移 位,计算 。 左移n位 左移n/2位 计算XY。 左移 左移
1
例1:阶乘函数
阶乘函数定义: 阶乘函数定义:
1 n! = n( n − 1)! n=0 n>0
注意: 注意: 每一个递归函数都必须有非递归定义 的初始值,否则递归函数就无法计算。 的初始值,否则递归函数就无法计算。 算法描述: 算法描述:
int Factorial(int n) { if (n==0) return 1; else return (n*Factorial(n-1)); (n*Factorial(n}
Θ(1)
2T(n/2)
Θ(n)
当n = 1 当n > 1
θ(1) 即T(n) = 2T(n/2)+ θ(n)
当n = 1 当n > 1
用套用公式法求此递归方程解的渐进阶得: 用套用公式法求此递归方程解的渐进阶得: T(n) = Θ(nlogn)
18
第7节 快速排序(Quicksort) 快速排序(Quicksort)
O(1) 2T(n/2) O(1)
当n = 1 当n > 1
时间复杂性递归方程: 时间复杂性递归方程:
θ(1) T(n) = θ(1) + 2T(n/2) + θ(1)
θ(1) 即 T(n) = 2T(n/2) + θ(1)
当n = 1 当n > 1
7
∴ T(n) = Θ(n)
第3节 二分搜索技术(Binary Search) 二分搜索技术( Search)
用套用公式法求此递归方程解的渐进阶得: 用套用公式法求此递归方程解的渐进阶得:
T(n) =θ(n )
13
3
改进上述算法, 改进上述算法,计算n/2 * n/2矩阵的10个加 减和7个乘法:
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 – A12 )(B11 + B12) 然后, 个加减: 然后,计算n/2 * n/2矩阵的8个加减: C11 = M5 + M4 – M2 + M6 C12 = M1 + M2 C21 = M3 + M4 C22 = M5 + M1 – M3 – M7
例:用分治法实现合并排序
(1) 算法设计
9 4 8 6 2 1 3 7
Divide
9 4 8 6 2 1 3 7
MergeMerge-Sort
4 6 8 9
MergeMerge-Sort
1 2 3 7
Combine
1 2 3 4 6 7 8 9
16
合并排序算法可递归地描述如下: 合并排序算法可递归地描述如下:
3
问题
分解问题
Divide Conquer
子问题
……
子问题 求解子问题 子问题解 子问题
求解子问题 …… 求解子问题 子问题解 合并子问题解 原问题的解 子问题解
Combine
4
(二)分治算法的分析 二 分治算法的分析 分析过程: 分析过程:
建立递归方程T(n) 求解递归方程T(n) 递归方程的建立方法
总之, 总之,
θ(1) T(n) = aT(n/b) + D(n) + C(n)
n=0 n>0
5
求解递归方程T(n) 求解递归方程T(n)
可用第一章介绍的求解递归方程解的渐进阶的方法求解。 可用第一章介绍的求解递归方程解的渐进阶的方法求解。
求一个非空集合中的最大数。 例: 求一个非空集合中的最大数。 (1)算法设计 )
29 14 15 1 6 10 32 12
问题分解
29 14 15 1 6 10 32 12
求解子问题
29
求解子问题
32
合并子问题
32
6
(2)算法时间复杂性分析
Divide阶段所花时间: 阶段所花时间: 阶段所花时间 Conquer阶段所花时间: 阶段所花时间: 阶段所花时间 Combine阶段所花时间: 阶段所花时间: 阶段所花时间
}
17
(2)合并排序算法复杂性分析
若n=1, T(n)=Θ(1)
Divide 阶段的时间复杂性: 阶段的时间复杂性: Conquer阶段的时间复杂性: 阶段的时间复杂性: 阶段的时间复杂性 Combine阶段的时间复杂性: 阶段的时间复杂性: 阶段的时间复杂性
θ(1) T(n) = 2T(n/2) + θ(n) + θ(1)
14
(2)算法复杂性分析 建立递归方程: 建立递归方程:
θ(1) T(n) = 2 7T(n/2)+ O(n ) 当n = 2 当n > 2
用套用公式法求此递归方程解的渐进阶得: 用套用公式法求此递归方程解的渐进阶得:
T(n) = θ(n
log 2 7
) ≈ θ(n
2.81
)
15
第6节 合并排序(Merge Sort) 合并排序( Sort)
12
阶方阵的乘积可以直接计算出来。 当n=2时,2个2阶方阵的乘积可以直接计算出来。 当n>2时,计算8个n/2阶方阵的乘积和4个n/2阶 个 方阵的加法。 上述分治法的计算时间T(n)的递归方程为: 上述分治法的计算时间 的递归方程为: 的递归方程为
θ(1) T(n) = 2 8T(n/2) + O(n ) 当n = 2 当n > 2
(1) 二分搜索算法的分治思想 (2) 二分搜索递归算法
算法描述: 算法描述:
int BS(int a[ ], int left, int right, int x) ( ) { if(left<=right) {mid=(left+right)/2; if (x==a[mid]) return mid; if(x>a[mid]) return BS(a,mid+1,right,x); else return BS(a,left,mid-1,x); } else return NULL; }
对于输入的子数组a[p r], 对于输入的子数组a[p : r],按以下三个步骤进行 排序: 排序:
1. 分解(Divide) 分解(Divide)
以a[p]为基准元素将a[p:r]划分成3段: a[p]为基准元素将 为基准元素将a[p:r]划分成 划分成3 a[p:qa[p:q-1], a[q], a[q+1:r] 使得: 使得: a[p:q-1]中的任何一个元素小于等于 a[p:q-1]中的任何一个元素小于等于a[q]; 中的任何一个元素小于等于a[q]; a[q+1:r]中的任何一个元素大于等于 a[q+1:r]中的任何一个元素大于等于a[q]。 中的任何一个元素大于等于a[q]。
当n<c, T(n) = θ(1). 划分(Divide)阶段的时间复杂性: 划分(Divide)阶段的时间复杂性: 划分问题为a个子问题,每个子问题大小为1/b, 划分问题为a个子问题,每个子问题大小为1/b, 划分时间D(n)可直接得到 可直接得到。 划分时间D(n)可直接得到。 递归求解(Conquer)阶段的时间复杂性: 递归求解(Conquer)阶段的时间复杂性: aT(n/b) 合并(Combine)阶段的时间复杂性: C(n) 合并(Combine)阶段的时间复杂性:
(Strassen’s algorithm for matrix multiplication) )
(一)算法设计
输入:两个n*n矩阵 和 输入:两个n*n矩阵X和Y n*n矩阵 输出: 和 的乘积 输出:X和Y的乘积 通常,计算X*Y的时间复杂性为 的时间复杂性为O(n3), 通常,计算 的时间复杂性为 现给出一个复杂性为O(n2.81)的算法。 的算法。 现给出一个复杂性为 的算法
T(n)=O(logn)。 。
9
n=0 n>0
求解递归方程解的渐进解得:
第4节 大整数的乘法
(一)算法设计 输入: 位二进制整数 位二进制整数X和 输入:n位二进制整数 和Y 输出: 和 的乘积 输出:X和Y的乘积 将每两个一位数的乘法或加法看作一步运算。 将每两个一位数的乘法或加法看作一步运算。 通常, 通常,计算X*Y的时间复杂性为O(n2), 现给出一个复杂性为O(n1. 59)的算法。
8
时间复杂性分析
分解( 分解(Divide)阶段所花时间: )阶段所花时间: O(1) T(n/2) 递归求解( 递归求解(Conquer)阶段所花时间: )阶段所花时间: 合并( 合并(Combine)阶段所花时间: )阶段所花时间: O(1)
时间复杂性递归方程:
θ(1) T(n) = T(n/2)+ θ(1)
第二章 递归与分治
第1节 递归的概念
递归函数:一个使用函数自身给出定义的函数。 递归函数:一个使用函数自身给出定义的函数。 递归算法:一个直接或间接调用自身的算法。 递归算法:一个直接或间接调用自身的算法。 在计算机算法设计与分析中,使用递归技术往往使 在计算机算法设计与分析中, 函数的定义和算法的描述简洁且易于理解。 函数的定义和算法的描述简洁且易于理解。 有些数据结构如二叉树等, 有些数据结构如二叉树等,由于其本身固有的递归 特别适合用递归的形式来描述。还有一些问题, 性,特别适合用递归的形式来描述。还有一些问题, 虽然其自身没有明显的递归结构, 虽然其自身没有明显的递归结构,但用递归技术来求 解使设计出的算法简洁易懂且容易分析。 解使设计出的算法简洁易懂且容易分析。
Template <class Type> void MergeSort (Type a[ ], int left, int right) { if (left<right)
//至少有两个元素 //至少有两个元素 {int i=(left+right)/2; //取中点 //取中点 ( )
MergeSort(a, left, i); ( ) MergeSort(a, i+1, right); ) ( Merge(a, b, left, right); //将两个有序子段和并 //将两个有序子段和并 Copy(a, b, left, right); //从数组b复制到数组a //从数组 复制到数组a 从数组b }
(二)算法复杂性分析 建立递归方程: 建立递归方程:
θ(1) T(n) = 3(T/2) + θ(n)
当n = 1 当n > 1
Байду номын сангаас1.59
用套用公式法求此递归方程解的渐进阶得: 用套用公式法求此递归方程解的渐进阶得:
T(n) = θ(n
log 2 3
) = θ(n
)
11
第5节 Strassen矩阵乘法 Strassen矩阵乘法
2
第2节 分治法(Divide-and-Conquer) 分治法(Divide-and-Conquer) 的基本思想
(一)分治算法的设计 一 分治算法的设计
分治算法的设计过程分为三个阶段: 分治算法的设计过程分为三个阶段: • 分解(Divide)阶段: 分解(Divide)阶段 阶段: 将整个问题划分为多个子问题; 将整个问题划分为多个子问题; • 递归求解(Conquer)阶段: 递归求解(Conquer)阶段: (递归调用正在设计的算法)求解每个子问题; 递归调用正在设计的算法)求解每个子问题; • 合并(Combine)阶段: 合并(Combine)阶段: 合并子问题的解,形成原始问题的解。 合并子问题的解,形成原始问题的解。
C11 C12 C C 22 21
=
A11 A 21
A12 A22
B11 B 21
B12 B22
由此可得: 由此可得
C11= A11 B11 + A12 B21 C12= A11 B12 + A12 B22 C21= A21 B11 + A22 B21 C22= A21 B12 + A22 B22
X=
n/2位 n/2位 位 位 A B
Y=
n/2位 n/2位 位 位 C D
XY = (A2n/2 + B)(C2n/2 + D) = AC2n + (AD + BC)2n/2 + BD = AC2n + ((A − B)(D − C) + AC + BD)2n/2 + BD
10
算法: 算法:
计算A-B和D-C; 和 计算 计算n/2位乘法 、BD、(A-B)(C-D); 计算 位乘法AC、 、 位乘法 计算(A-B)(C-D)+AC+BD; 计算 AC左移 位,((A-B)(C-D)+AC+BD)左移 位,计算 。 左移n位 左移n/2位 计算XY。 左移 左移
1
例1:阶乘函数
阶乘函数定义: 阶乘函数定义:
1 n! = n( n − 1)! n=0 n>0
注意: 注意: 每一个递归函数都必须有非递归定义 的初始值,否则递归函数就无法计算。 的初始值,否则递归函数就无法计算。 算法描述: 算法描述:
int Factorial(int n) { if (n==0) return 1; else return (n*Factorial(n-1)); (n*Factorial(n}
Θ(1)
2T(n/2)
Θ(n)
当n = 1 当n > 1
θ(1) 即T(n) = 2T(n/2)+ θ(n)
当n = 1 当n > 1
用套用公式法求此递归方程解的渐进阶得: 用套用公式法求此递归方程解的渐进阶得: T(n) = Θ(nlogn)
18
第7节 快速排序(Quicksort) 快速排序(Quicksort)
O(1) 2T(n/2) O(1)
当n = 1 当n > 1
时间复杂性递归方程: 时间复杂性递归方程:
θ(1) T(n) = θ(1) + 2T(n/2) + θ(1)
θ(1) 即 T(n) = 2T(n/2) + θ(1)
当n = 1 当n > 1
7
∴ T(n) = Θ(n)
第3节 二分搜索技术(Binary Search) 二分搜索技术( Search)
用套用公式法求此递归方程解的渐进阶得: 用套用公式法求此递归方程解的渐进阶得:
T(n) =θ(n )
13
3
改进上述算法, 改进上述算法,计算n/2 * n/2矩阵的10个加 减和7个乘法:
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 – A12 )(B11 + B12) 然后, 个加减: 然后,计算n/2 * n/2矩阵的8个加减: C11 = M5 + M4 – M2 + M6 C12 = M1 + M2 C21 = M3 + M4 C22 = M5 + M1 – M3 – M7
例:用分治法实现合并排序
(1) 算法设计
9 4 8 6 2 1 3 7
Divide
9 4 8 6 2 1 3 7
MergeMerge-Sort
4 6 8 9
MergeMerge-Sort
1 2 3 7
Combine
1 2 3 4 6 7 8 9
16
合并排序算法可递归地描述如下: 合并排序算法可递归地描述如下:
3
问题
分解问题
Divide Conquer
子问题
……
子问题 求解子问题 子问题解 子问题
求解子问题 …… 求解子问题 子问题解 合并子问题解 原问题的解 子问题解
Combine
4
(二)分治算法的分析 二 分治算法的分析 分析过程: 分析过程:
建立递归方程T(n) 求解递归方程T(n) 递归方程的建立方法
总之, 总之,
θ(1) T(n) = aT(n/b) + D(n) + C(n)
n=0 n>0
5
求解递归方程T(n) 求解递归方程T(n)
可用第一章介绍的求解递归方程解的渐进阶的方法求解。 可用第一章介绍的求解递归方程解的渐进阶的方法求解。
求一个非空集合中的最大数。 例: 求一个非空集合中的最大数。 (1)算法设计 )
29 14 15 1 6 10 32 12
问题分解
29 14 15 1 6 10 32 12
求解子问题
29
求解子问题
32
合并子问题
32
6
(2)算法时间复杂性分析
Divide阶段所花时间: 阶段所花时间: 阶段所花时间 Conquer阶段所花时间: 阶段所花时间: 阶段所花时间 Combine阶段所花时间: 阶段所花时间: 阶段所花时间
}
17
(2)合并排序算法复杂性分析
若n=1, T(n)=Θ(1)
Divide 阶段的时间复杂性: 阶段的时间复杂性: Conquer阶段的时间复杂性: 阶段的时间复杂性: 阶段的时间复杂性 Combine阶段的时间复杂性: 阶段的时间复杂性: 阶段的时间复杂性
θ(1) T(n) = 2T(n/2) + θ(n) + θ(1)
14
(2)算法复杂性分析 建立递归方程: 建立递归方程:
θ(1) T(n) = 2 7T(n/2)+ O(n ) 当n = 2 当n > 2
用套用公式法求此递归方程解的渐进阶得: 用套用公式法求此递归方程解的渐进阶得:
T(n) = θ(n
log 2 7
) ≈ θ(n
2.81
)
15
第6节 合并排序(Merge Sort) 合并排序( Sort)
12
阶方阵的乘积可以直接计算出来。 当n=2时,2个2阶方阵的乘积可以直接计算出来。 当n>2时,计算8个n/2阶方阵的乘积和4个n/2阶 个 方阵的加法。 上述分治法的计算时间T(n)的递归方程为: 上述分治法的计算时间 的递归方程为: 的递归方程为
θ(1) T(n) = 2 8T(n/2) + O(n ) 当n = 2 当n > 2
(1) 二分搜索算法的分治思想 (2) 二分搜索递归算法
算法描述: 算法描述:
int BS(int a[ ], int left, int right, int x) ( ) { if(left<=right) {mid=(left+right)/2; if (x==a[mid]) return mid; if(x>a[mid]) return BS(a,mid+1,right,x); else return BS(a,left,mid-1,x); } else return NULL; }