计算机算法设计与分析基础(第五章减治法)
算法设计与分析 第5章 减治策略和变治策略
元素的求解过程与n个元素求解过程的联系,使问题的求解直接通
过表达式来求解,从而简化问题的求解难度。
一般采用自顶向下的分析方法,但求解时往往采用自底向上的
求解过程。这也是递归的方法。
(2)减去一个常量因子
在规模中减去一个常量因子,使求解的规模成倍的缩小,从而
提高问题求解的效率。
(3)减去的规模可变。 根据求解过程的变化来确定每次规模减少的程度。 具体实例:
减治策略及变治策略
减治策略
利用一个问题给定实例的解与该问题较小实例的解之间的关系, 使原问题求解过程简化的方法称之为减治策略。 可利用递归或者非递归的方法进行问题的求解。一般分为三类: (1)减去一个常量。 也就是在求解过程中将原来的求解规模减小一个固定的常数,
比如原来有n个元素,通过减治之后,编程n-1个元素,并且建立n个
实例
将原始序列先转化成另一种存储形式,然后再进行排序以简化
排序算法,比如:
1、堆以及堆排序
2、平衡二叉树
此外,复杂问题简化以降低求解难度: 1、多项式求解:霍纳法则
2、进制之间的转换问题。
此外,还有一些具体问题的求解方法均可采用变治策略。
1、直接插入排序
2、拓扑排序
3、全排列问题
4、子集问题
变治策略
变治策略也就是将原始问题变换成更容易求解的实例,然后对变化
后的实例进行求解。
主要ቤተ መጻሕፍቲ ባይዱ如下类型:
(1)变换为同样问题的更简单的实例,也就是实例化简。
(2)变换为同样问题实例的不同形式,也成为改变表现。
(3)变换为不同问题的实例,使问题更易求解,成为问题简化。
6-1剪枝-概述
COMPUTER ALGORITHM最大利益优先——分支限界算法分支限界法就是最佳优先(包括广度优先在内)的搜索法。
分支限界法将要搜索的结点按评价函数的优劣排序,让好的结点优先搜索,将坏的结点剪去。
所以准确说,此方法应称为界限剪支法。
分支限界法中有两个要点:分支限界法是最佳优先搜索法12评价函数的构造;搜索路径的构造。
评价函数的构造评价函数要能够提供一个评定候选扩展结点的方法,以便确定哪个结点最有可能在通往目标的最佳路径上。
一个评价函数f(d)通常可以由两个部分构成:⑴从开始结点到结点d的已有耗损值g(d),和⑵再从结点d到达目标的期望耗损值h(d)。
即:f(d) = g(d) + h(d)通常g(d)的构造较易,h(d)的构造较难。
在回溯法中,每次仅考察一条路径,因而只需要构造这一条路径即可:前进时记下相应结点,回溯时删去最末尾结点的记录。
这比较容易实现。
在分支限界法中,是同时考察若干条路径,那么又该如何构造搜索的路径呢?搜索路径的构造对每一个扩展的结点,建立三个信息: 这样一旦找到目标,即可逆向构造其路径。
用一个表保存准备扩展的结点,称为Open表。
用一个表保存已搜索过的结点,称为Closed表。
该结点的名称; 它的评价函数值; 指向其前驱的指针;分支限界法的一般算法⑴计算初始结点s 的f(s); [s, f(s), nil]放入Open;⑵while (Open ≠Φ) {⑶从Open 中取出[p, f(p), x](f(p)为最小);⑷将[p, f(p), x]放入Closed;⑸若p 是目标,则成功返回;否则⑹{ 产生p 的后继d 并计算f(d) ;对每个后继d有二种情况:①d ∈Closed || ∈Open ;②d Open && d Closed 。
⑺{ 若([d, f’(d), p]∈Closed || [d, f’(d), p]∈Open) && f(d)<f’(d),则删去旧结点并将[d, f(d), p] ⑻将[d, f(d), p] 插入到Open 中}}}。
5-第五章 减治法
2.比较v和 A[x]
确定查找范围
5.6.3 二叉查找树的查找和插入
• 二叉查找树:左子树的值小于根顶点,右 子树大于根顶点。
小结
5.4 生成组台对象的算法
• 组合问题 1、计数 2、结构
组合问题
5.4.1 生成排列
用减一思想生成{1,2,…,n}所有排列。
Johnson-trotter算法
• 字典序---增序排队
5.4.2 生成子集
1、挤压序: 所 2、是否存在—种生成比特串的最小变化算法,使得每
一个比特串和它的直接前趋之间仅仅相差一 个比特 位。
n / 2 ,它要求找出这样一个元素,该元素比列表中的—半元素大,又比另—半元素
小。这个中间的值被称为中值,它在数理统计中是—个非常重要的量。
• 类似快速排序的分区做法
• 例
15 15
效率分析: 1)平均效率 2)最差效率
5.6.2 插值查找
插值查找用于有序数组,“插值”代替了折 半查找中的中间值 1.计算
• 最坏输入是一个严格递减的数组,这种输 入的比较次数是
• 最好的情况下(升序),在外部循环的每 次送代中,比较操作只执行一次
• 平均
5.2深度优先查找和广度忧先查找
• 什么叫图的遍历 从图的任意点出发沿着一些边访问图中的 所有顶点,且使每个顶点仅被访问一次,这就 叫图的遍历. • 我们来看一下图的遍历的两种方法: 1.深度优先搜索 2.广度优先搜索
第一种算法是深度优先查找的一个简单应用:执行一次DFS遍 历,并记住顶点变成死端(即退出遍历栈)的顺序。将该次序反过来 就得到了拓扑排序的一个解。
第二种算法基于减(减一)治技术的一个直 接实现:不断地做这样—件事,在余下的有向 图中求出一个源,它是一个没有输入边的顶点, 然后把它和所有从它出发的边都删除。
算法设计与分析部分算法伪代码
第三章 蛮力法1.选择排序SelectionSort(A[0..n-1])for i=0 to n-2 domin=ifor j=i+1 to n-1 doif A[j]<A[min]min=jswap A[i] and A[min]2.冒泡排序BubbleSort(A[0..n-1])// 输入:数组A,数组中的元素属于某偏序集// 输出:按升序排列的数组Afor i=0 to n-2 dofor j=0 to n-2-i doif A[j+1]<A[j] swap A[j] and A[j+1]3.改进的冒泡算法ALGORITHM BubbleSortImproved( A[0,…,n –1] )// 冒泡排序算法的改进// 输入:数组A,数组中的元素属于某偏序集// 输出:按升序排列的数组Afor i ← 0 to n – 2 doflag ← Truefor j ← 0 to n – 2 – i doif A[j+1] < A[j]swap(A[j], A[j+1])flag ← False// 如果在某一轮的比较中没有交换,则flag为True,算法结束returnif flag = True4. 顺序查找算法算法 SwquentialSearch2(A[0...n],k)//顺序查找算法的实现,它用了查找键来作限位器//输入:一个n个元素的数组A和一个查找键K//输出:第一个值等于K的元素的位置,如果找不到这样的元素就返回 -1A[n]<--ki<--0while A[i]!=K doi<--i+1if i<n return iElse return -15. 蛮力字符串匹配算法 BruteForceStringMatch(T[0...n-1],P[0...m-1])//该算法实现了蛮力字符串匹配代表一段文本//输入:一个n个字符的数组T[0...n-1]// 一个m个字符的数组P[0..m-1]代表一个模式//输出:如果查找成功的话,返回文本的第一个匹配字串中第一个字符的位置, // 否则返回-1For i<--0 to n-m doj<--0While j<m and P[j]=T[i+j]doj<--i+1If j=m return ireturn -1合并排序最差Θ(nlog2n)快速排序最优Θ(nlog2n)最差Θ(n2)平均Θ(1.38nlog2n)选择排序 Θ(n2)冒泡排序 Θ(n2)插入排序最差Θ(n2)最优 Θ(n)平均 Θ(n2)第四章 分治法合并排序算法 MergeSort(A[0..n-1] )排序 // 递归调用mergesort来对数组 A[0...n-1]// 输入:一个可排序数组A[0..n-1]// 输出:非降序排列的数组A[0..n-1]if n > 1n/2 -1]copy A[0.. n/2 -1] to B[0..n/2 -1]copy A[ n/2 ..n-1] to C[0..MergeSort( B )MergeSort( C )Merge( B,C,A )两个数组合并的算法算法 Merge(B[0..p-1],C[0..q-1],A[0..p+q-1])//将两个有序数组合并成一个有序的数组和C[0...q-1]//输入:两个有序数组B[0...p-1]//输出:A[0..p+q-1]中已经有序存放了B和C中的元素 i=0,j=0,k=0;while i<p and j<q do≤C[j]if B[i]A[k]=B[i], i=i+1elseA[k]=C[j], j=j+1k=k+1if i=pcopy C[j..q-1] to A[k..p+q-1]elsecopy B[i..p-1] to A[0..p+q-1]快速排序算法QuickSort(A[l..r])// 使用快速排序法对序列或者子序列排序或者序列本身A[0..n-1]// 输入:子序列A[l..r]// 输出:非递减序列Aif l < rs ← Partition( A[l..r] )QuickSort( A[l..s-1] )QuickSort( A[s+1..r] )//s是中轴元素/基准点,是数组分区位置的标志实现分区的算法Partition( A[l..r] )// 输入:子数组A[l..r]// 输出:分裂点/基准点pivot的位置p ← A[l]i ← l; j ← r+1repeat≥ prepeat i ←i + 1until A[i]≤ prepeat j ← j – 1 until A[j]swap( A[i], A[j] )≥ juntil iswap( A[i], A[j] )swap( A[l], A[j] )return j折半查找BinarySearch( A[0..n-1], k )// 输入:已排序大小为n的序列A,待搜索对象k// 输出:如果搜索成功,则返回k的位置,否则返回-1 l=0,r=n-1;While l≤rmid= (l+r)/2if k = A[mid] return midelse if k < A[mid] r=m-1else l=m+1return -1Strassen矩阵Strassen方法M1=A11(B12-B22)M2=(A11+A12)B22M3=(A21+A22)B11M4=A22(B21-B11)M5=(A11+A22)(B11+B22)M6=(A12-A22)(B21+B22)M7=(A11-A21)(B11+B12)第五章 减治法插入排序ALGORITHM InsertionSort( A[0..n-1] )// 对给定序列进行直接插入排序// 输入:大小为n的无序序列A// 输出:按非递减排列的序列Afor i ← 1 to n-1 dotemp ← A[i]j ← i-1while j ≥ 0 and A[j] > temp doA[j+1] ← A[j]j ← j –1A[j+1] ←temp深度优先查找算法 BFS(G)//实现给定图的深度优先查找遍历//输入:图G=<V,E>//输出:图G的顶点,按照被DFS遍历第一次访问到的先后次序,用连续的整数标记,将V中的每个顶点标记为0,表示还“未访问”count =0//记录这是第几个访问的节点标记为 unvisitedmark each vertex with 0//∈ V dofor each vertex vif v is marked with 0dfs(v)dfs(v)//递归访问所有和v相连接的未访问顶点,然后按照全局变量count的值//根据遇到它们的先后顺序,给它们附上相应的数字count = count + 1mark v with countv dofor each vertexw adjacent toif w is marked with 0dfs(w)广度优先BFS(G)/实现给定图的深度优先查找遍历//输入:图G=<V,E>//输出:图G的顶点,按照被BFS遍历第一次访问到的先后次序,用连续的整数标记,将V中的每个顶点标记为0,表示还“未访问”count =0mark each vertex with 0for each vertex v∈ V dobfs(v)bfs(v)//递归访问所有和v相连接的未访问顶点,然后按照全局变量count的值//根据遇到它们的先后顺序,给它们附上相应的数字count = count + 1mark v with countinitialize queue with vwhile queue is not empty doa = front of queuefor each vertex w adjacent to a doif w is marked with 0count = count + 1mark w with countadd w to the end of the queueremove a from the front of the queue拓扑排序第六章 变治法Gauss消去法GaussElimination(A[1..n], b[1..n])// 输入:系数矩阵A及常数项 b// 输出:方程组的增广矩阵等价的上三角矩阵for i=1 to n doA[i][n+1] =b[i]for j= i+1 to n dofor k = i to n+1 do– A[i][k]*A[j][i]/A[i][i]A[j][k] = A[j][k]堆排序堆排序主要包括两个步骤:对于给定的数组构造相应的堆。
算法分析与设计多媒体课件
很多算法的效率都取决于输入的组织
最坏情况: Cworst(n) – 对于规模为n的输入,最大的消 耗
最好情况: Cbest(n) –对于规模为n的输入,最小的消耗 平均情况: Cavg(n)–对于规模为n的输入,“平均”的消
耗
基本操作执行的次数体现在典型输入中
不是最好最坏情况的平均
将规模n的实例划分为几种类型,同种实例所需要的基 本操作执行次数一样,然后我们得到或者假设各种输入 的概率分布,以推导出我们的平均次数
2021/3/31
算法设计与分析
17
输入规模与基本操作举例
问题
输入规模的度量
基本运算
在长度为n的列表中 列表节点数目,例如 n 按关键字查找
关键字比较
两个矩阵相乘
矩阵的维度或者元素的 个数
两个数相乘
对 于 给 定 的 数 n, 判 断是否为素数
n的大小(经常转化为 二进制表示,即为二进 制的位数)
f1(n) + f2(n) O(max{g1(n), g2(n)})
2021/3/31
算法设计与分析
32
使用极限比较增长次数
0 order of growth of T(n) < order of growth of g(n)
lim T(n)/g(n) =
n→∞
c > 0 order of growth of T(n) = order of growth of g(n)
Θ(g(n)):增长率与g(n)相同的一类函数f(n)
Ω(g(n)):增长至少与g(n)相同的一类函数f(n)
2021/3/31
算法设计与分析
27
Big-oh
成立的条件是对于足够大的n>n0,存在大于0的常数c ,使得以上图形满足,后面符号的两个条件相同
第 五 章 减治法
算 分 析 与 设 计
西南科技大学
金块问题
有一个老板有一袋金块。每个月将有两 名雇员会因其优异的表现分别被奖励一 个金块。按规矩,排名第一的雇员将得 到袋中最重的金块,排名最后的雇员将 得到袋中最轻的金块。如果每个月都有 新的金块周期性的加入袋中,则每个月 都必须找出最轻和最重的金块。假设有 一台比较重量的仪器,我们希望用最少 的比较次数找出最轻和最重的金块。
算 分 析 与 设 计
西南科技大学
直接插入排序实现方法
减一技术下,该方法遵循的思路是:假设对较 小数组 A[0..n-2]排序问题已经解决了,得到一 个大小为n-1的有序数组。然后将要排序的第n 个元素,插入到数组的适合位置上,得到大小 为n的有序数组 A[0..n-1]。伪代码如下: void InsertionSort(a[]) {for(i=1;i<n-1;i++) //从第二个记录起进行插入 for (j=i-1; j>=0;j--) if a[j+1]-(a[j]) < 0 Swap(a[j+1], a[j]); }
算 分 析 与 设 计
西南科技大学
俄式乘法☺ 俄式乘法☺
算法思想:两个A和B数相乘,把数A每 次除以2,直到为0为止,另一个数B则不 断加倍,若第数A未除尽时,则数B应加 上自己。 7×8的计算步骤: 7 8 3 16+ 8 1 32+ 16 + 8
算 分 析 与 设 计
西南科技大学
约瑟夫斯问题( 约瑟夫斯问题(一)
算 分 析 与 设 计
西南科技大学
减常数因子减治法
减常数因子减治法的一个 典型算法就是折半查找 (Bin_Search)。它搜索 一个排序好的数组,将查 找目标与数组的中间位置 的元素相比,比它大则递 归查找数组的左边,反之 亦然。这个每次迭代都将 问题减小为原来的1/2。 折半查找每次都消去一个 常数因子2,因此其时间 效率为O(logn)。
计算机算法设计与分析基础(第六章变治法)
★ 变治策略
★ 预排序
★ 高斯消去法 ★ 平衡查找树(略)
★ 堆与优先队列(略)
★ 堆排序(略) ★ 霍纳法则和二进制幂 ★ 问题化简 ★ 本章习题
★ 变治策略
通用的算法设计方法,基于变换的思想
变:变换问题更容易求解 治:对变换后的问题求解
3 种主要类型
实例化简:问题求解变得更简单,如预排序
while ( i≤n-1 )
runlength←1,runvalue←A[i] // 行程长度 = 等值元素个数 while ( i+runlength≤n-1 and A[i+runlength] = runvalue )
runlength ++ // 与下一个元素相等则行程长度+1
if ( runlength > ModeFrequency ) ModeFrequency←runlength,modeValue←runvalue i←i+runlength // 跳过本行程,i 始终指向行程的第一个元素 return ( ModeValue, ModeFrequency )
需要与辅助列表中已加入的 k-1个元素比较,共 k-1 次。
最差效率:
T ( n) ( k 1) 1 ... n 1 (n2 )
k 1
n
变治法 —— 预排序(nlogn型),排序后 等值元素一定相邻 扫描统计:模式具有最多的相邻元素,需比较 n -1 次。 PresortMode_1(A[0...n-1]) // 行程算法 对数组A排序 // 排序结果 { 1, 5, 5, 5, 6, 7, 7 } i←0,ModeFrequency←0 // 最大频率,最大行程长度
第7章 减治法(《算法设计与分析(第3版)》C++版 王红梅 清华大学出版社)
比较对象,若 k 与中间元素相等,则查找成功;若 k 小于中间元素,则在中间元
算 法 设
计
素的左半区继续查找;若 k 大于中间记录,则在中间元素的右半区继续查找。不
与 分
析
断重复上述过程,直到查找成功,或查找区间为空,查找失败。
( 第
版 )
k
清 华
大
学
[ r1 … … … rmid-1 ] rmid [ rmid+1 … … … rn ] (mid=(1+n)/2)
Page 4
3
7.1.2 一个简单的例子——俄式乘法
【问题】俄式乘法(russian multiplication)用来计算两个正整数 n 和 m 的乘积
,运算规则:如果 n 是偶数,计算 n/2×2m;如果 n 是奇数,计算(n-1)/2×2m+
m;当 n 等于 1 时,返回 m 的值。
算
法
俄式乘法的优点?
与 分 析
2. 测试查找区间[low,high]是否存在,若不存在,则查找失败,返回 0;
( 第
3. 取中间点 mid = (low+high)/2; 比较 k 与 rmid,有以下三种情况:
版 )
3.1 若 k < rmid,则 high = mid - 1;查找在左半区进行,转步骤2;
清 华
3.2 若 k > rmid,则 low = mid + 1;查找在右半区进行,转步骤2;
Page 12
7.2.2 选择问题
【想法】假定轴值的最终位置是 s,则: (1)若 k=s,则 rs 就是第 k 小元素; (2)若 k<s,则第 k 小元素一定在序列 r1 ~ rs-1 中; (3)若 k>s,则第 k 小元素一定在序列 rs+1 ~ rn 中。
第4章:减治法——《算法笔记
第4章:减治法——《算法笔记思考:减治提供了⼀种思考问题的⽅式原问题与减⼀问题的关系原问题划分成保持语义的⼦问题,可能规整划分,可能划分不定我觉得减治与分治的共同点在于:1.问题的分解 2.⼦问题语义的保持(可以使⽤递归)减治只需求解⼀个⼦问题,减法了⽆需求解的⼦问题分治法需要归总⼦问题,并且归总的过程存在丰富的语义总⽽⾔之,分为两个思路:1.从减⼀问题转化为原问题。
线性的数学归纳2.去除不必要的⼦问题,减⼩规模减去⼀个常量减去⼀个常量因⼦减去的规模可变减去⼀个常量规模为n的问题 ——>规模为n-1的问题减去⼀个常量因⼦规模为n的问题 ——>规模为n/2的问题减去的规模可变gcd(m,n)=gcd(n,m mod n)1.插⼊排序,将未排序元素插⼊已排序序列。
前⽅有序,后⽅⽆序。
插⼊动作:⼆分法搜索位置。
已排序检查算法,⼤多数已排序序列排序2.拓扑排序⽆环有向图1.深搜2.减⼀治:源删除算法在剩下的有向图中找源点(没有⼊边)3.⽣成组合对象n! (n-1)!剩余⼀个插⼊在n-1排列中满⾜最⼩变化要求johnson trotter算法字典序⽣成排列⽣成⼦集幂集:所有⼦集的集合减⼀:从空集开始,选择加⼀个元素与否——>两个新⼦集位串表⽰:每个位表⽰是否选中单个元素挤压序:位串之间最⼩变化:格雷码4.减常数因⼦算法折半查找假币问题:折半查找,三折查找俄式乘法:nxm=(n/2)x2m (n-1)/2 x2m+m位表⽰5.减可变规模算法每次迭代减⼩的规模都不同第k⼩元素第k个顺序统计量中值排序,选中值基于划分的算法:快速选择算法:遍历⼀次,选择位置k元素A[k],划分分成⼤于,⼩于两部分。
解决了更⼀般的问题:根据k⼤元素,划分了数组插值查找:假定数组分布为线性递增,线上照点⼆分查找:数字分布不定⼆叉查找树的查找与插⼊左<根<右习题:渡河问题:船容纳两个⼩孩或⼀个⼤⼈交替问题:硬币前正后反——正反交替:相对位置数组:不要求下标从0开始n元素集合幂集:是否包含最后⼀个元素邻接矩阵检测连通性:寻找反例两两⽐赛⼀次,保证每个队伍不输给排名在后⾯的队伍:插排(冒泡可以么?)为什么同是基于⽐较,算法复杂度不⼀样?排序算法作⽤于链表?算法复杂度?是否要求随机访问插排i<j && A[i]>A[j] ⼀个倒置倒置数量对排序性能的影响?平均键值⽐较次数希尔排序dfs拓扑排序效率如何避免逆序结果顶点进⼊dfs栈的顺序取代退出栈的顺序寻找源或判定环使⽤源删除算法邻接矩阵,邻接表算法复杂度强连通分量:dfs,死端编号,颠倒边,重复不同路径数:排列组合⽣成排列算法:heap最后⼀个数与heap(n-1)交换⼀个元素n奇数:A[1]偶数:A[i]基于位串的算法按照挤压序⽣成⼦集⽣成位串算法递归/⾮递归基于⼆进制运算/数组⼆进制反射格雷码的⾮递归算法反转前⼀位串的最低⾮0位⽣成n元素k分量⼦集是否为最⼩变化算法格雷码与汉诺塔⼀个灯泡,n个开关。
算法设计与分析-第5章-减治法
0 T (n) T (n / 2) 1
n 1 n 1
所以,通常来说,应用减治法处理问题的效率是很高的, 一般是O(log2n)数量级。
5.2 查找问题中的减治法
5.2.1 折半查找 5.2.2 二叉查找树 5.2.3 选择问题
5.2.1
一、问题描述:
折半查找
应用折半查找方法在一个有序序列中查找值为k的记 录。若查找成功,返回记录k在序列中的位置,若查找失 败,返回失败信息。
low=1
பைடு நூலகம்
18>14
mid=3
mid=7 31>14 high=6
high=13
high=2
mid=1
7<14
low=2
mid=2
14=14
5.2.1 折半查找
三、算法设计
算法5.1——折半查找
1. low=1;high=n; //设置初始查找区间 2. 测试查找区间[low,high]是否存在,若不存在,则查找失败; 否则 3. 取中间点mid=(low+high)/2; 比较k与r[mid],有以下三种情况: 3.1 若k<r[mid],则high=mid-1;查找在左半区进行,转2; 3.2 若k>r[mid],则low=mid+1;查找在右半区进行,转2; 3.3 若k=r[mid],则查找成功,返回记录在表中位置mid;
{ int data; //结点的值,假设查找集合的元素为整型
BiNode *lchild, *rchild; //指向左、右子树的指针 };
算法5.2——二叉排序树的查找
BiNode * SearchBST(BiNode *root, int k) { if (root= =NULL) return NULL; else if (root->data==k) return root; else if (k<root->data) return SearchBST(root->lchild, k); else return SearchBST(root->rchild, k); }
算法设计与分析-减治法详解共65页
•
29、在一切能够接受法律支配的人类 的状态 中,哪 里没有 法律, 那里就 没有自 由。— —洛克
•
30、风俗可以造就法律,也可以废除 法律。 ——塞·约翰逊
6、最大的骄傲于最大的自卑都表示心灵的最软弱无力。——斯宾诺莎 7、自知之明是最难得的知识。——西班牙 8、勇气通往天堂,怯懦通往地狱。——塞内加 9、有时候读书是一种巧妙地避开思考的方法。——赫尔普斯 10、阅读一切好书如同和过去最杰出的人谈话。——计与分析-减治法详解
•
26、我们像鹰一样,生来就是自由的 ,但是 为了生 存,我 们不得 不为自 己编织 一个笼 子,然 后把自 己关在 里面。 ——博 莱索
•
27、法律如果不讲道理,即使延续时 间再长 ,也还 是没有 制约力 的。— —爱·科 克
•
28、好法律是由坏风俗创造出来的。 ——马 克罗维 乌斯
算法设计与分析 王红梅 第二版 第5章_ 减治法
舍弃13之前元素,{13,15} 舍弃15之后元素,{10,15}
{13,15} 舍弃13之后元素,{13} {13} {10,15} 舍弃10之前元素,{15} {15}
2015-5-2
第5章 减治法
Page 11
减治法的设计思想
算法5.1:两个序列中位数SearchMid 输入:两个长度为n的有序序列A和B 输出:序列A和B的中位数 1. 循环直到序列A和序列B均只有一个元素 1.1 a = 序列A的中位数; 1.2 b = 序列B的中位数; 1.3 比较a和b,执行下面三种情况之一: 1.3.1 若a=b,则返回a,算法结束; 1.3.2 若 a<b ,则在序列 A 中舍弃 a 之前的元素,在序列 B 中舍弃b之后的元素,转步骤1; 1.3.3 若a>b,则在序列A中舍弃a之后的元素,在序列B中 舍弃b之前的元素,转步骤1; 2. 序列A和序列B均只有一个元素,返回较小者;
2015-5-2
Reduce and Conquer Method
4
减治法的设计思想
减治法将问题划分为若干子问题,并且规模为n的 原问题的解与较小规模(通常是 n/2)的子问题的解之 间具有某种确定的关系:
(1)原问题的解只存在于其中一个较小规模的子问题中; (2)原问题的解与其中一个较小规模的解之间有某种对应关系。
二叉排序树的结点结构为: struct BiNode { int data; //结点的值,假设查找集合的元素为整型 BiNode *lchild, *rchild; //指向左、右子树的指针 };
算法5.2——二叉排序树的查找 BiNode * SearchBST(BiNode *root, int k) { if (root= =NULL) return NULL; else if (root->data==k) return root; else if (k<root->data) return SearchBST(root->lchild, k); else return SearchBST(root->rchild, k); }
第五章 减治法(包含作业)
Cbest (n) i n 1 (n)
i 1
2014-2-12 9
n 1
5.1 插入排序-效率分析
平均效率的精确分析基于对无序元素的研究,对于 随机序列的数组,
n Cavg (n) (n 2 ) 4
2
2014-2-12
10
排序算法-时间复杂度小节
插入排序最差Θ(n2) 最优 Θ(n) 平均 Θ(n2)
2014-2-12 7
5.1 插入排序-伪代码
ALGORITHM InsertionSort( A[0..n-1] )
// 对给定序列进行直接插入排序 // 输入:大小为n的无序序列A // 输出:按非递减排列的序列A
for i ← 1 to n-1 do temp ← A[i] j ← i-1 while j ≥ 0 and A[j] > temp do A[j+1] ← A[j] j ← j –1 A[j+1] ←temp
是否可以不产生1,2,3…n-1的这些中间结果?
2014-2-12
30
5.4.1 生成排列-JT
在排列的每一分量上画一个箭头。
移动元素:如果分量k 的箭头指向一个相邻的 较小元素,则该分量在排列中是移动的。 While 存在可移动元素
求最大的移动整数k,不断移动元素,直到没有元 素可移动为止,掉转所有大于k 的整数方向。
减常数(如1) :每此迭代规模减小n→n-1
2014-2-12
2
减治法-减常因子
减因子(如1/2):每此迭代规模减半n→ n/2
与分治法的区别?
2014-2-12
3
减治法-减可变规模
每此迭代减小的规模不同
计算机算法基础(第五章)PPT教学课件
if VISITED(w)=0 then //w未被检测//
call ADDQ(w,Q) //ADDQ将w加入到队列Q的末端//
VISITED(w)←1 //同时标示w已被访问//
endif
repeat
段:LCHILD, DATA,RCHILD//
if T≠0 then call VISIT(T) call PREORDER(LCHILD(T)) call PREORDER(RCHILD(T))
endif end PREORDER
2020/12/11
4
⑵后根次序周游 算法5.2 后根次序周游的递归表示 procedure POSTORDER(T) //T是一棵二元树。T的每个结点有三个信息
2020/12/11
6
注:
一棵二元树可由中根遍历序列+先根遍历序列、或 中根遍历序列+后根遍历序列唯一确定。但不能由先 根遍历序列+后根遍历序列唯一确定。
如已知一棵二元树的中根遍历次序是:
DGBEAFHC
先根遍历次序是:ABDGECFH
A
则这棵二元树唯一确定如下:
B
C
D
E
F
2020/12/11
G
H
② 访问邻接于v且尚未被访问的所有结点——这些结 点是新的未被检测的结点。将这些结点依次放置到一未检 测结点表(队列Q)中(末端插入) 。
③ 标记v已被检测。
④ 若未检测结点表为空,则算法终止;否则
⑤ 从未检测结点表的表头取一结点作为下一个待检
2020/12/11
11
测结点,
算法5.6 宽度优先检索算法
其中,t(0)≤c1。 归纳法证明t(n)≤c2n+c1,其中c2是一使得c2≥2c1的常数。 1)当n=0时,成立
减治法
第五章 减治法
5.4 生成组合对象的算法
方法:一开始从右往左的把 插入到 插入到12…(n-1)的位置中,然 的位置中, 方法:一开始从右往左的把n插入到 的位置中 后再调换方向从左往右把n插入到 插入到2…(n-1)中去。例如: 中去。 后再调换方向从左往右把 插入到 中去 例如:
开始 从右到左插入2 从右到左插入3 从左到右插入3 从右到左插入4 1 12 21 123 132 312 321 231 213 1234 1243 1423 4123 1324 1342 1432 4132 3124 3142 3412 4312 4321 3421 3241 3214 4231 2431 2341 2314 4213 2413 2143 2134
从左到右插入4
第五章 减治法
5.4 生成组合对象的算法
算法: 算法:JohnsonTrotter(n) //实现用来生成排列的 实现用来生成排列的Johnson-Trotter算法 实现用来生成排列的 算法 //输入:一个正整数 输入: 输入 一个正整数n //输出:{1,..,n}的所有排列的列表 输出: , , 的所有排列的列表 输出 ← ← ← ← 将排列初始化为 1 2 3 ... n While 存在移动元素 do 求最大的移动元素k 求最大的移动元素 将k和它所指向的元素互换 和它所指向的元素互换 调转所有大于k的元素的方向 调转所有大于 的元素的方向 将新排列加入到列表
Back
第五章 减治法
5.5 减可变规模算法
在减可变规模算法这种情况下,算法每次迭代的时候, 在减可变规模算法这种情况下,算法每次迭代的时候, 规模减小的模式都和另外依次迭代是不一样的。 规模减小的模式都和另外依次迭代是不一样的。计算最大公约 数的欧几里得算法是一个典型的例子。而别的实例还包括有: 数的欧几里得算法是一个典型的例子。而别的实例还包括有: 1、计算中值和选择问题 、 2、插值查找 、 3、二叉查找树的查找和插入 、 4、拈游戏 、
计算机算法设计与分析基础(第五章减治法)
6
29
7
31
8
35
9
38
10
42
11
46
12
49
13
52
low=1
设置初始区间
mid=7
high=13 查找区间为[1, 13] 取中点mid=7 比较r[7]与k,将查找调整到左半区
low=1 mid=3 low=1 high=2 mid=1 low=high=2 mid=2
high=6
查找区间为[1, 6] 取中点mid=3 比较 r[3]与k,将查找调整到左半区 查找区间为[1, 2] 取中点mid=1 比较r[1]与k,将查找调整到右半区 查找区间为[2, 2] 取中点mid=2 比较r[2]与k,查找成功,返回mid的位置2
Johnson-Trotter 法生成排列
其实有的算法并不需要知道规模n-1的排列就可 以直接得到规模n的排列结果,Johnson-Trotter算法就 是其中一种。利用这一算法求得的排列序列还是相邻
序列变化最小的一个序列集合,也就是说下一个序列
与上一个序列仅仅交换了两个元素的位置 。
J-T方法举例
直接插入排序举例
待排序序列{89,45,68,90,29,34,17} 插入过程: InsertionSort ( A[0...n 1]) 89 45 {89} 不需比较 j V { {45,89} // 插入元素V 45 89 j for ( i 1 to n 1) do {45,68,89} 45 68 j i 89,90} {45,68, 1, V A[i ] {29,45,68, 0 and A[ j ] V ) while ( j 89,90} 45 68 {29,34,45,68 A[ 90} 后移 A[ j 1] 89, j ] // 29 45 {17,29,34,45,68, 89, 90} j j 1 插入次数=n-1=6 29 34 A[ j 1] V 比较次数=? 17 29 } // j 0 : 限位
5第五章 减治法
生成子集(Subset)
•背包问题中如何穷举出给定物品集合的所有子集? 背包问题中如何穷举出给定物品集合的所有子集? 背包问题中如何穷举出给定物品集合的所有子集
A={a1,a2,...,an}={a1,a2,...,an-1} ∪{an}
/
© School of Computer Science and Technology, SWUST
1)减去一个常量 2)减去一个常数因子 3)减去的规模是可变的
/
© School of Computer Science and Technology, SWUST
3
减(一)治技术
规模为n 的问题 规模为n-1 的子问题 f(n)=an f(n)=f(n-1)*a f(n)=a
© School of Computer Science and Technology, SWUST
22
选择问题(Selection Problem)
Procedure SELECT(A,n,k) integer n,k,m,r,j; m 1;r n+1;A(n+1) +∞; loop j r call PARTITION(m,j) case :k=j:return :k<j:r j :else:m j+1 endcase repeat End SELECT
子问题的解
n>1 n=1
原始问题的解
/
© School of Computer Science and Technology, SWUST
4
减(半)治技术
规模为n 的问题 规模为n/2 的子问题
an=(an/2)2
n是偶数 是偶数
an=(a(n-1)/2)2 *a n是奇数 是奇数 an =a n=1
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
子数组有序,用折半查找为插入元素在其中找到一个合适的位 置。 例题:在有序表{ 7, 14, 18, 21, 23, 29, 31, 35, 38, 42, 46, 49, 52 }中查找值为14的记录的过程如图所示。
折半查找
0 1
7
2
14
3
18
4
21
5
23
插入排序效率分析
插入排序效率分析
Tworst (n) 1 i 1 2 ... ( n 1) n( n 1) ( n ) 2 i 1 j 0 i 1
输入规模:元素个数 n 基本操作:比较操作 A[ j ] > V 效率类别:输入 A 为升序,每次插入只需比较1次 —— 最佳效率 输入 A 为降序 —— 最差效率,其他 —— 平均效率 n 1 最佳效率:要插入 n-1个元素,共需比较 n-1 次(线性效率) Tbest ( n) 1 n 1 ( n) 也可据伪码计算: i 1 最差效率 对每个元素如第 i 个元素插入,从 j = i-1 比较到 j = 0,共 i 次比较, n 1 i n 1 即插入元素1A[ i ] 要与前面的全部元素都比较一次。 1 2
减一策略: 设规模减一 { 1, 2, ..., n-1 } 的全排列已解决,有 (n-1) ! 个 把 n 插入到这 (n-1) ! 个排列中去,就解决了规模 n 的问题,即得 { 1, ..., n } 全排列。在每个 { 1, ..., n-1 } 排列中插入 n 的位置有(n-1) + 1 = n 个, 排列数 = (n-1) ! ×n = n ! 问:这样得到的排列是唯一的吗? 答:是。(n-1) ! 个排列是唯一的,在其不同位置插入一个新元素 n, 结果
生成组合对象算法:生成排 列
生成组合对象
组合对象:满足一定约束条件的集合 组合数学:指出组合对象有多少个 —— 组合数(通常呈指数级增长) 如何生成:本节内容 生成排列 (前面讲过蛮力法)
生成集合元素
{ a1 , a2 , ..., an }
的全排列,可解释为:
—— 生成集合元素下标 { 1, 2, ..., n } 的全排列,排列数 = n ! 个
插入法生列排列
举例:求n=3的排列 方法:在n=2的排列中插入3,
在n=1的排列中插入2。 过程: 在 1 中从右到左插入2得到 12,21 在 12 中从右到左插入3得到 123,132,312 在 21 中从右到左插入3得到 213,231,321
于是得 {123,132,312,213,231,321}
分治法和减治法区别
分治法是对分解的子问题分别求解,需要对子问 题的解进行合并,而减治法只对一个子问题求解, 并且不需要进行解的合并。应用减治法(例如减 半法)得到的算法通常具有如下递推式:
0 T (n) T (n / 2) 1
n 1 n 1
5.1插入排序
简介
插入排序的过程类似玩牌时整理手中纸牌的过程。就 是对 n 个元素 A [ 0, ... , n-1 ] 排序的一种方法。它的 基本思想是:每步将一个待排序的对象按照其关键字 的大小,插到前面已经排好序的序列中的适当位置, 直到全部对象插入完毕为止。 常用的插入排序有:直接插入排序、折半插入排序、 链表插入排序和希尔排序,它们划分的依据是在排好 序的序列中寻找插入位置所使用方法的不同。
直接插入排序举例
待排序序列{89,45,68,90,29,34,17} 插入过程: InsertionSort ( A[0...n 1]) 89 45 {89} 不需比较 j V { {45,89} // 插入元素V 45 89 j for ( i 1 to n 1) do {45,68,89} 45 68 j i 89,90} {45,68, 1, V A[i ] {29,45,68, 0 and A[ j ] V ) while ( j 89,90} 45 68 {29,34,45,68 A[ 90} 后移 A[ j 1] 89, j ] // 29 45 {17,29,34,45,68, 89, 90} j j 1 插入次数=n-1=6 29 34 A[ j 1] V 比较次数=? 17 29 } // j 0 : 限位
//加入元素3
降低规模的减治法可以用来求幂集。 减治法的缺点也是在求解规模为n的问题时,需要 得到规模为n-1的问题的解。这一过程是可以避免的, 使用位串法求解集合幂集就是其中的一种解决方案。
平均效率:比最差效率快2倍。若遇到基本有序数组,比选择排序 Tavg (n) n2 / 4 (n2 ) 和 冒泡排序的性能略优。
5.4 生成组合对象的算法 1、生成排列
排列问题指的是对于给定的多个元素求其 中各种可能的序列。为了简单起见,这里仅仅 考虑1到n之间的整数的排列问题。 下面介绍三种生成方法: (1)插入法 (2)Johnson-Trotter 法 (3)字典顺序法
掌握减治法的基本思想及在常见问题问题中的应用。
2
概念与算法策略
算法策略
减治法:利用给定规模与较小规模问题解之间的关系求解问题 的方法。 实现 —— 从顶向下:规模减小(递归) 从底向上:规模增大(非递归) 原问题(规模n) 减常量法:常量通常为1(每此迭代规模减小n→n-1 (规模n) 原问题 ) 减常因子法:常因子通常为 2(每此迭代规模减半n→ n/2 ) 减可变规模法:每次减去的规模不同 子问题(规模n-1) 子问题(规模
在排列的每一分量上画一个箭头。 求最大的移动整数k,不断移动元素,直到没有元素 可移动为止,掉转所有大于k 的整数方向。 移动元素:如果分量k 的箭头指向一个相邻的较小 元素,则该分量在排列中是移动的。 例n=3,从123开始:
1 23 1 32 3 1 2 32 1 23 1 2 1 3
Johnson-Trotter 法生成排列
其实有的算法并不需要知道规模n-1的排列就可 以直接得到规模n的排列结果,Johnson-Trotter算法就 是其中一种。利用这一算法求得的排列序列还是相邻
序列变化最小的一个序列集合,也就是说下一个序列
与上一个序列仅仅交换了两个元素的位置 。
J-T方法举例
3→ { } { 1 } { 2 } { 1, 2 } { 3 } { 1, 3 } { 2, 3 }{ 1, 2, 3 } 23=8
减治法生成幂集
例n=3 方法:在n=2的幂集中加入元素3,在n=1的幂集中 加入 , {1}, {2}, {1,2} //加入元素2 , {1}, {2}, {1,2}, {3}, {1,3}, {2,3}, {1,2,3}
字典顺序生成排列
尽管Johnson-Trotter算法非常高效,但是似乎 不是那么直观,不太符合人们的思维习惯。事 实上比较自然的算法称为“字典排序( lexicographic order)算法”,它是根据单词在 字典中的排列顺序得到的算法。
字典生成顺序举例
例n=3 在{1,2,3}中按字典顺序选择: 123 132 213 231 312 321
生成幂集:减一算法
减一算法(实现 —— 自底向上,规模加一)
从空集开始,每次向已生成的每个子集中加入一个元素,如此继续, 直到所有 n 个元素都加入为止。
例:生成 A = { a1, a2, a3 } 全部子集
n 开始 { } 1→ { } { 1 } 2→ { } { 1 } { 2 } { 1, 2 } 子集(元素下标表示) 子集数 20=1 21=2 22=4
68 90 29 34 17
V
68 90 29 34 17
j V
89 90 29 34 17 89 90 29 34 17
j V
68 89 90 34 17
j V
45 68 89 90 17 34 45 68 89 90
j V
思考:为什么是右扫描插入V?
下划线为待插元素
插入排序算法与算例
6
29
7
31
8
35
9
38
10
42
11
46
12
49
13
52
low=1
设置初始区间
mid=7
high=13 查找区间为[1, 13] 取中点mid=7 比较r[7]与k,将查找调整到左半区
low=1 mid=3 low=1 high=2 mid=1 low=high=2 mid=2
high=6
查找区间为[1, 6] 取中点mid=3 比较 r[3]与k,将查找调整到左半区 查找区间为[1, 2] 取中点mid=1 比较r[1]与k,将查找调整到右半区 查找区间为[2, 2] 取中点mid=2 比较r[2]与k,查找成功,返回mid的位置2
5.1插入排序
插入排序
对 n 个元素 A [ 0, ... , n-1 ] 排序(非降序为例) 减一策略 —— 分析过程自顶向下(规模减小) 减去一个元素 A[n-1] , 对 A[ 0,...,n-2 ] 排序(非降序) 原问题的解 = 减一规模的解 + A[n-1] 对数组递归减一,分解到仅一个元素为止;再合并得到原问题解。 插入算法 —— 有三种方法,左右扫描称统称 直接插入法 左扫描:从左向右扫描有序子数组,遇到第一个≥A[n-1] 元素为止,在该元素前插入A[n1] . 若未找到,则插在最后。 右扫描:从右向左扫描有序子数组,遇到第一个≤A[n-1] 元素为止,在该元素后插入A[n1] . 若未找到,则插在最前。 常用:右扫描法。问:理由是什么? 理由:子数组若有等值元素,右扫描插入时需移动的元素个数少。 —— 它插在等值元素后,前面等值元素都不用移动位置