算法设计与分析-第5章-减治法
算法设计与分析 第5章 减治策略和变治策略
元素的求解过程与n个元素求解过程的联系,使问题的求解直接通
过表达式来求解,从而简化问题的求解难度。
一般采用自顶向下的分析方法,但求解时往往采用自底向上的
求解过程。这也是递归的方法。
(2)减去一个常量因子
在规模中减去一个常量因子,使求解的规模成倍的缩小,从而
提高问题求解的效率。
(3)减去的规模可变。 根据求解过程的变化来确定每次规模减少的程度。 具体实例:
减治策略及变治策略
减治策略
利用一个问题给定实例的解与该问题较小实例的解之间的关系, 使原问题求解过程简化的方法称之为减治策略。 可利用递归或者非递归的方法进行问题的求解。一般分为三类: (1)减去一个常量。 也就是在求解过程中将原来的求解规模减小一个固定的常数,
比如原来有n个元素,通过减治之后,编程n-1个元素,并且建立n个
实例
将原始序列先转化成另一种存储形式,然后再进行排序以简化
排序算法,比如:
1、堆以及堆排序
2、平衡二叉树
此外,复杂问题简化以降低求解难度: 1、多项式求解:霍纳法则
2、进制之间的转换问题。
此外,还有一些具体问题的求解方法均可采用变治策略。
1、直接插入排序
2、拓扑排序
3、全排列问题
4、子集问题
变治策略
变治策略也就是将原始问题变换成更容易求解的实例,然后对变化
后的实例进行求解。
主要ቤተ መጻሕፍቲ ባይዱ如下类型:
(1)变换为同样问题的更简单的实例,也就是实例化简。
(2)变换为同样问题实例的不同形式,也成为改变表现。
(3)变换为不同问题的实例,使问题更易求解,成为问题简化。
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)。
AA-chapter 5-01 减治法
18
插入排序
• 常用的插入排序有:
– 直接插入排序 – 折半插入排序 – 链表插入排序 – 希尔排序
• 它们的区别只在于 它们的区别 如何在排好序的序列 如何在排好序的序列 中寻找插入的位置。
算法分析与设计 兰州大学信息学院
19
5.1 直接插入排序
ALGORITHM InsertionSort( A[0 A[0..n ..n-1] ) // 对给定序列进行直接插入排序 // 输入:大小为n的无序序列A // 输出:按非递减排列的序列A for i ← 1 to n-1 do //把A[i]插入到A[1 A[1..i ..i-1] temp ← A[i] j ← i -1 while j ≥ 0 and A[j] > temp do A[j+1 A[j+ 1] ← A[j] j ← j-1 A[j+1 A[j+ 1] ← temp
InsertionSort( A[0 InsertionSort( A[0..n ..n-1] ) // 对给定序列进行直接插入排序 // 输入:大小为n的无序序列A // 输出:按非递减排列的序列A for i ← 1 to n-1 do temp ← A[i A[i] j ← i-1 while j ≥ 0 and A[j] > temp do A[j+1 A[j+ 1] ← A[j] j ← j-1 A[j+1 A[j+ 1] ← temp
算法分析与设计 兰州大学信息学院
21
5.1 直接插入排序 实例 (蓝色代表已排好序)
89 | 45 68 90 29 34 17 45 89 | 68 90 29 34 17
InsertionSort( A[0 InsertionSort( A[0..n ..n-1] ) // 对给定序列进行直接插入排序 // 输入:大小为n的无序序列A // 输出:按非递减排列的序列A for i ← 1 to n-1 do temp ← A[i A[i] j ← i-1 while j ≥ 0 and A[j] > temp do A[j+1 A[j+ 1] ← A[j] j ← j-1 A[j+1 A[j+ 1] ← temp
第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 中。
生成组合对象的算法(减治法)
生成组合对象的算法(减治法)下面将详细介绍生成组合对象的减治法算法:1.定义问题:首先需要明确所要生成的组合对象的特征和属性。
例如,如果生成组合对象是包含固定数量的不同颜色的气球,那么问题的定义就是生成所有可能的气球颜色组合。
2.划分子问题:接下来,需要将问题划分为更小的子问题。
对于生成组合对象的问题,可以将其分解为生成单个组合对象的子问题。
在上述例子中,可以将其划分为生成单个气球颜色的子问题。
3.设计基本情况:在减治法中,需要定义一个基本情况,当问题的规模达到基本情况时,可以直接解决问题。
在上述例子中,当只有一个气球需要生成时,就可以直接生成所有可能的颜色。
4.减小问题规模:使用递归方法将问题规模逐渐减小。
在上述例子中,可以通过迭代每种颜色的气球来生成组合对象。
每次迭代,都解决一个气球颜色的子问题,并将其与其他已生成的气球组合。
5.合并子问题:将解决子问题的结果合并为整体解决方案。
在上述例子中,可以将每个气球颜色子问题的解合并为组合对象的解。
通过将每种颜色的气球与已生成的组合对象组合,可以生成所有可能的组合对象。
6.返回解决方案:最后,返回所有生成的组合对象作为最终的解决方案。
减治法的关键是确定如何划分子问题,并设计适当的方法来减小问题规模和合并子问题的解。
对于生成组合对象的问题,子问题的划分可以根据组合对象的特征和属性进行确定。
递归方法的使用可以确保问题规模不断减小,直到达到基本情况。
需要注意的是,生成组合对象可能会涉及到大量的计算和存储。
为了提高算法的效率,可以考虑使用剪枝等技术来减少不必要的计算和存储。
总结:生成组合对象的减治法算法通过将问题划分为较小的子问题,并逐步减小问题规模和合并子问题的解决方案来解决复杂问题。
这种算法的关键是确定子问题的划分和适当的规模减小和合并方法。
减治法是解决生成组合对象问题的一种有效方法,可以根据具体问题的特征和属性进行具体的实现。
减治法(一)
减治法(⼀)这篇⽂章将讨论:1) 减治法的思想和策略2) ⼏个数据结构⾥⾯经典的使⽤减治策略的算法:插⼊排序,深度和⼴度优先查找,拓扑排序(都是减⼀治的)通过 1) 2)明⽩减治策略的基本思想和⽅法,也对经典数据结构做⼀番新的审视,从减治策略的⾓度来重新看待这些算法。
⽽在后⾯,将继续花⼏篇⽂章讨论减治策略的其他问题:排列问题,⼦集问题,减常因⼦算法,减可变规模算法。
----------------------------------------------------------------------------------------------------------------------------------------------------减治技术利⽤了⼀个问题给定实例的解和同样问题较⼩实例的解之间的某种关系。
⼀旦建⽴了这种关系,就可以从顶⾄下递归的来⽤该关系,也可以从底⾄上⾮递归的来运⽤该关系:1)减去⼀个常量2)减去⼀个常量因⼦3)减去的规模是可变的1) ⼀般来说减去的⼀个常量是1,即如果不断地解决n-1规模的问题就能解决n规模的问题,(偶⽽也有减2的,⽐较少)⽐如求a^n的值,既可以递归的从上到下求解,也可以⾮递归的从下往上构造(连续乘法,注意⽅法和蛮⼒⼀样,但思考问题的⾓度不⼀样)2) ⼀般来说减去的⼀个常数因⼦是2(即将原问题规模分为2),其实减常因⼦的减治法可以看做是分治的变种,只不过它只对划分⼦规模后的⼀个部分求解。
例如仍然是求a^n,我们可以这样来思考:3)对于减可变规模的例⼦,那就更少了,因为效率越⾼的算法显然越难找到。
⼀个例⼦是欧⼏⾥得算法,前⾯也写过了:总之,减治的3种⽅法,以及⼀个简单的例⼦就像上⾯所述。
-------------------------------------------------------------------------------------------------------------------------------------------------1,插⼊排序1) 最简单的排序⽅法,写过,也很简单。
算法设计与分析王红梅第1章绪论
2021/6/12
}
15
清华大学出版社
算法设计与分析
⑷ 伪代码——算法语言
伪代码(Pseudocode):介于自然语言和 程序设计语言之间的方法,它采用某一程序 设计语言的基本语法,操作指令可以结合自 然语言来设计。
优点:表达能力强,抽象性强,容易理解
使用方法:7 ± 2
2021/6/12
16
清华大学出版社
欧几里德算法
1. r = m % n; 2. 循环直到 r 等于0
2.1 m = n; 2.2 n = r; 2.3 r = m % n; 3. 输出 n ;
2021/6/12
算法设计与分析
17
清华大学出版社
算法设计与分析
1.1.4 算法设计的一般过程
1.理解问题
2.预测所有可能的输入
3. 在精确解和近似解间做选择
算法设计与分析
1.1 算法的基本概念
1.1.1 为什么要学习算法 1.1.2 算法及其重要特性 1.1.3 算法的描述方法 1.1.4 算法设计的一般过程 1.1.5 重要的问题类型
2021/6/12
5
清华大学出版社
算法设计与分析
1.1.1 为什么要学习算法
理由1:算法——程序的灵魂
➢ 问题的求解过程:
14
清华大学出版社
算法设计与分析
#include <iostream.h>
int CommonFactor(int m, int n)
欧
{ int r=m % n;
几
while (r!=0)
里
{ m=n;
德
n=r;
算
r=m % n; }
算法设计与分析 王红梅 第二版 第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); }
减治法
第5章减治法(Decrease and Conquer)减治法的基本思想规模为n的原问题的解与较小规模(通常是n/2)的子问题的解之间具有关系:(1)原问题的解只存在于其中一个较小规模的子问题中;(2)原问题的解与其中一个较小规模的解之间存在某种对应关系。
由于原问题的解与较小规模的子问题的解之间存在这种关系,所以,只需求解其中一个较小规模的子问题就可以得到原问题的解。
2减治法的基本思想一旦建立了这种关系,就可以从顶至下(递归),也可以从底至上(非递归)的来运用Example, n!A top down (recursive) solutionA bottom up (iterative) solution3减治法的类型减治法有三种变种:1)减去一个常量2)减去一个常数因子3)减去的规模是可变的gcd(m, n)4减(一)治技术a problem of size nsubproblemof size n-1a solution to thesubprobleme.g., n!a solution tothe original problem5减(半) 治技术a problem of size nsubproblemof size n/2a solution to thesubprobleme.g., Binary searcha solution tothe original problem67典型的分治法subproblem 2 of size n /2subproblem 1 of size n /2a solution to subproblem 1 a solution to the original problema solution to subproblem 2a problem of size ne.g., mergesort减治与分治的区别考虑以下指数问题: 计算a n减一法Bottom-up: iterative (brute Force) Top-down:recursive分治法:减常因子法:a n= a*a*a*a*...*aa n= a n-1* a if n > 1= a if n = 1a n= a ⎣n/2 ⎦* a ⎡n/2⎤if n > 1= a if n = 1a n = (a n/2 ) 2if n is even and positive= (a(n-1)/2 ) 2 * a if n is odd and > 1 = a if n = 1O (log2n) O (n log2n)89111)2/(0)(>=⎩⎨⎧+=n n n T n T 所以,通常来说,应用减治法处理问题的效率是很高的,一般是O (log 2n)数量级。
减治法
第五章 减治法
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 : 限位
算法分析TheAnalysisofAlgorithms
Repeat
89 | 45 68 90 29 34 17
算法 InsertionSort(A[0..n-1])
//用插入排序对给定数组排序 //输入:一个可排序数组 //输出:非降序列数组A
for i1 to n-1 do{ vA[i]; ji-1;
while (j≥0 and A[j]>v){ A[j+1}A[j]; jj-1;
23
插值查找(Interpolation
•有序数组查找 的另一种方法
search)
由直线方程可得:
键值比较次数小于 log2log2n+1
© School of Computer Science and Technology, SWUST
24
二叉树的查找与插入
最差效率Θ(n),平均效率Θ(logn)
jr call PARTITION(m,j)
调用划分函数
case
:k=j:return
:k<j:rj
:else:mj+1 endcase
两个新的子问题
repeat
End SELECT
T(n)=T(n/2)+(n+1)
© School of Computer Science and Technology, SWUST
, W(1)=0
© School of Computer Science and Technology, SWUST
18
俄式乘法(Multiplication á la
两个大整数m和n乘法
russe)
n n * m= —2 * 2 * m
n -1 n为偶数 n * m= —2— * 2 * m + m
算法设计与分析减治法
第4页,共62页。
减可变规模:每此迭代减小的规模不同
5
第5页,共62页。
• 减常量: • 5.1 插入排序
5.2 深度优先查找与广度优先查找 5.3 拓扑排序 5.4 生成组合对象的算法
5.5 减常因子算法 5.6 减可变规模算法
6
第6页,共62页。
5.1 插入排序
• 如何用减一法对一个数组A[0..n-1]排序? • 也就是如何建立n规模与n-1规模之间的关系? • 假设n-1规模的数组A[0..n-2]已经解决, • 则需要考虑元素A[n-1],在这个有序数组中处于何处? • 常用的插入排序有:直接插入排序、折半插入排序 • 它们划分的依据是在排好序的序列中寻找插入位置所使用方
• 广度优先搜索的效率与图的表示有关吗? • 对邻接矩阵表示的图:遍历的效率为
Θ( V 2) • 对邻接链表表示的图:遍历的效率为
Θ( V + E )
第19页,共62页。
acd e be f
cad f d ac
eab f f bce
gh j h g i ih j j g i
19
总结
数据结构 顶点顺序的种类
?升序排列?每次插入只需比较一次111nnincnibest???12?平均效率的精确分析基于对无序元素的研究对于随机序列的数组平均效率的精确分析基于对无序元素的研究对于随机序列的数组422nnncavg13评价?插入排序最差n2?优最优n?均平均n2?合并排序最差nlog2n?快速排序最优nlog2n?最差n2?平均138nlog2n序选择排序n2序冒泡排序n2遇到基本有序数组表现优异性能可结合数组表现优异性能可结合快速排序1452深度优先查找一个dfs输出序列是
13
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
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); }
二叉查找树 = 平衡二叉树?
5.2.2 二叉查找树
二、问题分析
由二叉查找树的定义,在二叉查找树root中查找给定值k 的过程是: ⑴ 若root是空树,则查找失败; ⑵ 若k=根结点的值,则查找成功; ⑶ 否则,若k<根结点的值,则在root的左子树上查找; ⑷ 否则,在root的右子树上查找; 上述过程一直持续到k被找到或者待查找的子树为空, 如果待查找的子树为空,则查找失败。
1
2 4 3 · · ·· ·
3 4 · · · · · · · · · ·
· · 4 · · 3
5.2.3 选择问题
选择问题的例子 A[1…28]={8,33,17,51,57,49,35,11,25,37,14,3,2,1 3,52,12,6,29,32,54,5,16,22,23,7,61,36,9},求A的 中位数元素,即第14小元素。(k=14)
{8,33,17,51,57,49,35,11,25,37,14,3,2,13,52,12,6,29,32,54,5,16,22,23,7,61,36,9}
{3,7,5,6,2,8,11,25,37,14,35,49,13,52,12,57,29,32,54,51,16,22,23,17,61,36,33,9}
5.2.1 折半查找
四、算法分析 判定树——描述折半查找的判定过程。
长度为n的判定树的构造方法为:
(1)当n=0时,判定树为空; (2)当n>0时,判定树的根结点是有序表中序号为 mid=(n+1)/2的记录,根结点的左子树是与有序表r[1] ~ r[mid-1]相对应的判定树,根结点的右子树是与r[mid+1] ~
34
31 3
31 3
81
T(n)=1 n=1 T(n)=2T(n/2)+1 n>1
T(n)=O(n)-蛮力法 不是所有的分治法都比简 单的蛮力法有效
5.1 减治法概述
二、分治法和减治法区别
应用分治法(例如二分法)得到的算法通常具有如下递推式:
g (n) T (n) 2T (n / 2) c
5.1 减治法概述
一、设计思想 规模为n的原问题的解与较小规模(通常是n/2)的子 问题的解之间具有关系: (1)原问题的解只存在于其中一个较小规模的子问题中; (2)原问题的解与其中一个较小规模的解之间存在某种 对应关系。 由于原问题的解与较小规模的子问题的解之间存在这 种关系,所以,只需求解其中一个较小规模的子问题就可 以得到原问题的解。
k [ r1 … … … rmid-1 ] rmid [ rmid+1 … … … rn ] (mid=(1+n)/2)
如果k<rmid查找这里
如果k>rmid查找这里
5.2.1 折半查找
例:查找值为14的记录的过程: 0 1 2 3 4 5 6 7 8 9 10 11 12 13
7 14 18 21 23 29 31 35 38 42 46 49 52
5.2.3 选择问题
寻找 第k小元素问题 二、问题分析 考虑快速排序中的划分过程,一般情况下,设待划分的序列 为ri ~ rj,选定一个轴值将序列ri ~ rj进行划分,使得比轴值小的 元素都位于轴值的左侧,比轴值大的元素都位于轴值的右侧,假 定轴值的最终位置是s,则: (1)若k=s,则rs就是第k小元素; (2)若k<s,则第k小元素一定在序列ri ~ rs-1中; (3)若k>s,则第k小元素一定在序列rs+1 ~ rj中; 无论哪种情况,或者已经得出结果(如果轴值恰好是序列的中 值),或者将选择问题的查找区间减少一半。
j=6
j<k,在右边区间找第k(=14-6=8)小元素
{11,25,37,14,35,49,13,52,12,57,29,32,54,51,16,22,23,17,61,36,33,9} {9,11,37,14,35,49,13,52,12,57,29,32,54,51,16,22,23,17,61,36,33,25}
二叉查找树的查找效率就在于只需要查找两个子树之一
在二叉查找树中查找关键字值为35,95的过程:
50 30 50
5.2.2 二叉查找树 实例
80
40 90 85 88 32 20
30
80
20
35 32
40
35 85
90
88
简述查找过程?
5.2.2 二叉查找树
三、算法设计
二叉排序树的结点结构为: struct BiNode
r[n]相对应的判定树。
5.2.1 折半查找
具有11个结点的判定树
6
3 1
2 4 5 7
9 10
log2 n 1
8
11
在表中查找任一记录的过程,即是判定树中从根结点到 该记录结点的路径,和给定值的比较次数等于该记录结点在 树中的层数。具有n个结点的判定数的深度为 log2 n 1 。
选择问题的例子
选择问题的查找过程示例(查找第4小元素)
查找过程:以5为轴值划分
序 列 4<5 , 只 在 左 侧 查 找
5 2 2
3 3 3
8 4 4
1 1
4 6 5 6
9 9
2 7 8 7
,以 2 为轴值划分序列 4>2
,只在右侧查找,以4为轴 值划分序列 4 = 4 ,轴值即 为第4小元素
1 · · ·· ·
5.2.3 选择问题
一、问题描述: 设无序序列 T =(r1, r2, …, rn),T 的第k(1≤k≤n)小元素 定义为T按升序排列后在第k个位置上的元素。给定一个序 列T和一个整数k,寻找 T 的第k小元素的问题称为选择问题。 特别地,将寻找第n/2小元素的问题称为中值问题。 在n个元素的无序数组中选择第k(1<=k<=n)小元素。 当k=1时,相当于找最小值。 当k=n时,相当于找最大值。 当k=n/2时,称中值。
5.2.1 折半查找
二、问题分析:
基本思想:在有序表中,取中间记录作为比较对象,若给 定值与中间记录的关键码相等,则查找成功;若给定值小 于中间记录的关键码,则在中间记录的左半区继续查找; 若给定值大于中间记录的关键码,则在中间记录的右半区 继续查找。不断重复上述过程,直到查找成功,或所查找 的区域无记录,查找失败。
5.2.2 二叉查找树
63 55 42 10 45 58 70 90 10 83 55
42
45 58 63
70 83 90
67
67
(a) 按63,90,55,58,70,42,10,45,83,67 的顺序构造的二叉排序树
(b) 按55,42,10,70,63,58,83,67,90,45 的顺序构造的二叉排序树
5.1 减治法概述
原问题 的规模是n
子问题 的规模是n/2
子问题的解
原问题的解
5.1 减治法概述
例:计算an的值,应用减治技术得到如下计算方法:
a n2 2 n a (a ) ( n - 1) 2 2 ´ ) a ( a
n 1 n 1 且是偶数 n 1 且是奇数
O (log2n)
应用分治法得到an的计算方法是:
a n 2 n 2 a a
n
a
n 1 n 1
O (n)
应用分治法计算an 。
5.1 减治法概述
如果 n 1
n 2
a
n
分析时 间性能
n a
32 31 3 9
a
2