第6章 函数-5Hanoi塔问题的递归求解
《Hanoi塔问题》课件

在游戏设计和人工智能领域,Hanoi塔问题可以作为解决游戏策略和决策问题的 模型。例如在围棋、象棋等游戏中,可以利用Hanoi塔问题的解法来设计更强大 的游戏AI。
PART 04
Hanoi塔问题的扩展和变 种
REPORTING
带限制的Hanoi塔问题
总结词
带限制的Hanoi塔问题是指在移动盘 子时,需要满足一些特定的限制条件 。
分治策略解法的优点是能够将问题分 解为更小的子问题,降低问题的复杂 度。但缺点是需要仔细设计子问题的 分解方式和合并方式,以确保能够正 确地解决问题。
PART 03
Hanoi塔问题的应用
REPORTING
在计算机科学中的应用
算法设计
Hanoi塔问题可以作为解决复杂算法问题的模型,例如在解决图论、动态规划 等算法问题时,可以利用Hanoi塔问题的特性来设计更高效的算法。
决。
在Hanoi塔问题中,递归解法的基本思 路是将问题分解为三个子问题:将n个 盘,最后将第n个盘子从
A柱移动到B柱。
递归解法的优点是思路简单明了,易于 理解。但缺点是对于大规模问题,递归 解法的时间复杂度较高,容易造成栈溢
出。
动态规划解法
动态规划解法是一种通过将问题分解为子问题并存储子问题的解来避免重复计算的方法。
数学模型的应用
汉诺塔问题可以通过数学模型进行描述和解决,如使用递归公式或动态规划方法。理解如何将实际问题转化为数 学模型,并运用数学工具进行分析和解决,是数学应用的重要能力。
对解决问题的方法论的启示
解决问题的思维方式
汉诺塔问题提供了一种独特的思维方式,即通过不断将问题分解为更小的子问题来解决。这种思维方 式有助于我们在面对复杂问题时,能够更加清晰地理解和分析问题,从而找到有效的解决方案。
scratch汉诺塔递归算法

Scratch汉诺塔递归算法1. 引言汉诺塔(Hanoi Tower)是一种经典的数学问题,它可以帮助我们理解递归算法的原理和应用。
在这个任务中,我们将使用Scratch编程语言来实现汉诺塔递归算法。
2. 汉诺塔问题简介汉诺塔问题源于印度传说中的一个故事。
据说,在一个庙里有三根针,第一根针上套着64个不同大小的金盘子,大的在下面,小的在上面。
庙里的和尚每天都要将这些金盘子从第一根针移动到第三根针上,但是移动时必须遵守以下规则:1.每次只能移动一个盘子;2.每次移动必须将较小的盘子放在较大的盘子上面;3.可以借助第二根针作为中转。
3. 算法设计思路要解决汉诺塔问题,我们可以使用递归算法。
递归是一种函数调用自身的方法。
对于汉诺塔问题来说,我们可以将其分解为三个步骤:1.将n-1个盘子从第一根针移动到第二根针(借助第三根针作为中转);2.将第n个盘子从第一根针移动到第三根针;3.将n-1个盘子从第二根针移动到第三根针(借助第一根针作为中转)。
这样,我们可以通过递归调用这三个步骤来解决汉诺塔问题。
4. Scratch实现在Scratch中实现汉诺塔递归算法,我们需要创建以下角色和代码块:4.1 角色设计我们需要创建三个角色来表示三根针,以及一个角色来表示金盘子。
每个角色都应该有一个变量来表示当前所在的位置。
4.2 代码块设计我们需要设计以下代码块来实现汉诺塔递归算法:4.2.1 初始化代码块在初始化时,我们需要将金盘子放置在第一根针上,并设置好每个金盘子的大小。
当绿旗被点击时把金盘子放置在第一根针上设置金盘子大小4.2.2 移动代码块移动一个金盘子的过程可以分为以下几步:1.判断当前金盘子是否在目标针上;2.如果在目标针上,结束移动;3.如果不在目标针上,找到下一个需要移动到的位置(借助另外一根针);4.将当前金盘子移动到下一个位置;5.递归调用移动代码块,将剩余的金盘子移动到目标针上。
当收到 [移动金盘子 v] 消息时如果 [当前位置 v] = [目标位置 v] ?那么结束此脚本否则设置 [下一个位置 v] 为 (3 - [当前位置 v] - [目标位置 v])把金盘子放置在第 [下一个位置 v] 根针上把金盘子移到第 [目标位置 v] 根针上发送消息 (移动金盘子) 给自己并等待 (0.5) 秒4.2.3 触发移动代码块为了触发整个移动过程,我们可以创建一个按钮,并在其点击事件中调用移动代码块。
汉诺塔问题求解思路

汉诺塔问题求解思路汉诺塔问题是⼀个经典的问题。
汉诺塔(Hanoi Tower),⼜称河内塔,源于印度⼀个古⽼传说。
⼤梵天创造世界的时候做了三根⾦刚⽯柱⼦,在⼀根柱⼦上从下往上按照⼤⼩顺序摞着64⽚黄⾦圆盘。
⼤梵天命令婆罗门把圆盘从下⾯开始按⼤⼩顺序重新摆放在另⼀根柱⼦上。
并且规定,任何时候,在⼩圆盘上都不能放⼤圆盘,且在三根柱⼦之间⼀次只能移动⼀个圆盘。
问应该如何操作?分析如果是初次接触类似的问题,乍看之下肯定会感觉⽆从下⼿。
要把64个圆盘从a柱⼦移动到c柱⼦上,第⼀步应该怎么做?虽然可以肯定,第⼀步唯⼀的选择是移动a最上⾯的那个圆盘,但是应该将其移到b还是c呢?很难确定。
因为接下来的第⼆步、第三步……直到最后⼀步,看起来都是很难确定的。
能⽴即确定的是最后⼀步:最后⼀步的盘⼦肯定也是a最上⾯那个圆盘,并且是由a或b移动到c——此前已经将63个圆盘移动到了c上。
也许你会说,管他呢,先随便试着移动⼀下好了。
如果你这么做,你会发现,接下来你会⾯临越来越多类似的选择,对每⼀个选择都“试”⼀下的话,你会偏离正确的道路越来越远,直到你发现你接下来⽆法进⾏为⽌。
如果将这个问题的盘⼦数量减为10个或更少,就不会有太⼤的问题了。
但盘⼦数量为64的话,你⼀共需要移动约1800亿亿步(18,446,744,073,709,551,615),才能最终完成整个过程。
这是⼀个天⽂数字,没有⼈能够在有⽣之年通过⼿动的⽅式来完成它。
即使借助于计算机,假设计算机每秒能够移动100万步,那么约需要18万亿秒,即58万年。
将计算机的速度再提⾼1000倍,即每秒10亿步,也需要584年才能够完成。
注:在我的笔记本电脑上,每秒⼤约能够移动6~8百万步。
虽然64个盘⼦超出了⼈⼒和现代计算机的能⼒,但⾄少对于计算机来说,这不是⼀个⽆法完成的任务,因为与我们⼈类不同,计算机的能⼒在不断提⾼。
分解问题⼀股脑地考虑每⼀步如何移动很困难,我们可以换个思路。
采用递归和非递归方法求解hannol问题

采用递归和非递归方法求解hannol问题汉诺塔问题是数学中的经典问题之一,也被认为是计算机科学中的经典问题。
它的解法可以使用递归或非递归的方法。
在本文中,我们将介绍并比较这两种解法。
汉诺塔问题的描述是:有三根柱子,A、B、C,初始时,A柱子上有n个盘子,这些盘子从小到大按顺序堆叠在一起。
现在需要将这n 个盘子从A柱子移动到C柱子上,期间可以借助B柱子。
移动盘子有以下几个规则:1.每次只能移动一个盘子;2.盘子只能从大盘子移到小盘子上;3.在移动过程中,可以借助柱子进行中转。
接下来,我们将先介绍递归解法。
递归解法:对于n个盘子,我们可以将问题分解为以下三个步骤:1.将n-1个盘子从A柱子移动到B柱子;2.将第n个盘子从A柱子移动到C柱子;3.将n-1个盘子从B柱子移动到C柱子。
递归解法的代码如下:```pythondef hanoi(n, A, B, C):if n == 1:print("Move disk %d from %s to %s" % (n, A, C)) else:hanoi(n-1, A, C, B)print("Move disk %d from %s to %s" % (n, A, C)) hanoi(n-1, B, A, C)```在这个递归函数中,n表示盘子的数量,A、B、C表示三根柱子。
当n为1时,直接将第一个盘子从A柱子移动到C柱子;否则,先将n-1个盘子从A柱子移动到B柱子,然后将第n个盘子从A柱子移动到C柱子,最后将n-1个盘子从B柱子移动到C柱子。
递归的过程中,会不断地将问题分解为子问题,直到子问题规模减小到1。
下面是一个具体的例子,假设有3个盘子,初始时都在A柱子上:```pythonhanoi(3, 'A', 'B', 'C')```输出结果为:```Move disk 1 from A to CMove disk 2 from A to BMove disk 1 from C to BMove disk 3 from A to CMove disk 1 from B to AMove disk 2 from B to CMove disk 1 from A to C```如上所示,递归解法将问题分解为子问题,然后逐步解决子问题,最后得到整体的解。
计算机算法设计和分析习题及答案解析

计算机算法设计与分析习题及答案一.选择题1、二分搜索算法是利用 A 实现的算法;A、分治策略B、动态规划法C、贪心法D、回溯法2、下列不是动态规划算法基本步骤的是 A ;A、找出最优解的性质B、构造最优解C、算出最优解D、定义最优解3、最大效益优先是A 的一搜索方式;A、分支界限法B、动态规划法C、贪心法D、回溯法4. 回溯法解旅行售货员问题时的解空间树是 A ;A、子集树B、排列树C、深度优先生成树D、广度优先生成树5.下列算法中通常以自底向上的方式求解最优解的是B ;A、备忘录法B、动态规划法C、贪心法D、回溯法6、衡量一个算法好坏的标准是 C ;A 运行速度快B 占用空间少C 时间复杂度低D 代码短7、以下不可以使用分治法求解的是 D ;A 棋盘覆盖问题B 选择问题C 归并排序D 0/1背包问题8. 实现循环赛日程表利用的算法是A ;A、分治策略B、动态规划法C、贪心法D、回溯法9.下面不是分支界限法搜索方式的是D ;A、广度优先B、最小耗费优先C、最大效益优先D、深度优先10.下列算法中通常以深度优先方式系统搜索问题解的是D ;A、备忘录法B、动态规划法C、贪心法D、回溯法11.备忘录方法是那种算法的变形; BA、分治法B、动态规划法C、贪心法D、回溯法12.哈夫曼编码的贪心算法所需的计算时间为B ;A、On2nB、OnlognC、O2nD、On13.分支限界法解最大团问题时,活结点表的组织形式是B ;A、最小堆B、最大堆C、栈D、数组14.最长公共子序列算法利用的算法是B;A、分支界限法B、动态规划法C、贪心法D、回溯法15.实现棋盘覆盖算法利用的算法是A ;A、分治法B、动态规划法C、贪心法D、回溯法16.下面是贪心算法的基本要素的是C ;A、重叠子问题B、构造最优解C、贪心选择性质D、定义最优解17.回溯法的效率不依赖于下列哪些因素 DA.满足显约束的值的个数B. 计算约束函数的时间C.计算限界函数的时间D. 确定解空间的时间18.下面哪种函数是回溯法中为避免无效搜索采取的策略BA.递归函数 B.剪枝函数 C;随机数函数 D.搜索函数19. D是贪心算法与动态规划算法的共同点;A、重叠子问题B、构造最优解C、贪心选择性质D、最优子结构性质20. 矩阵连乘问题的算法可由 B 设计实现;A、分支界限算法B、动态规划算法C、贪心算法D、回溯算法21. 分支限界法解旅行售货员问题时,活结点表的组织形式是 A ;A、最小堆B、最大堆C、栈D、数组22、Strassen矩阵乘法是利用A 实现的算法;A、分治策略B、动态规划法C、贪心法D、回溯法23、使用分治法求解不需要满足的条件是 A ;A 子问题必须是一样的B 子问题不能够重复C 子问题的解可以合并D 原问题和子问题使用相同的方法解24、下面问题 B 不能使用贪心法解决;A 单源最短路径问题B N皇后问题C 最小生成树问题D 背包问题25、下列算法中不能解决0/1背包问题的是 AA 贪心法B 动态规划C 回溯法D 分支限界法26、回溯法搜索状态空间树是按照 C 的顺序;A 中序遍历B 广度优先遍历C 深度优先遍历D 层次优先遍历27.实现合并排序利用的算法是A ;A、分治策略B、动态规划法C、贪心法D、回溯法28.下列是动态规划算法基本要素的是D ;A、定义最优解B、构造最优解C、算出最优解D、子问题重叠性质29.下列算法中通常以自底向下的方式求解最优解的是 B ;A、分治法B、动态规划法C、贪心法D、回溯法30.采用广度优先策略搜索的算法是A ;A、分支界限法B、动态规划法C、贪心法D、回溯法31、合并排序算法是利用 A 实现的算法;A、分治策略B、动态规划法C、贪心法D、回溯法32、背包问题的贪心算法所需的计算时间为 BA、On2nB、OnlognC、O2nD、On33.实现大整数的乘法是利用的算法C ;A、贪心法B、动态规划法C、分治策略D、回溯法34.0-1背包问题的回溯算法所需的计算时间为AA、On2nB、OnlognC、O2nD、On35.采用最大效益优先搜索方式的算法是A;A、分支界限法B、动态规划法C、贪心法D、回溯法36.贪心算法与动态规划算法的主要区别是B;A、最优子结构B、贪心选择性质C、构造最优解D、定义最优解37. 实现最大子段和利用的算法是B ;A、分治策略B、动态规划法C、贪心法D、回溯法38.优先队列式分支限界法选取扩展结点的原则是 C ;A、先进先出B、后进先出C、结点的优先级D、随机39.背包问题的贪心算法所需的计算时间为 B ;A、On2nB、OnlognC、O2nD、On40、广度优先是A 的一搜索方式;A、分支界限法B、动态规划法C、贪心法D、回溯法41. 一个问题可用动态规划算法或贪心算法求解的关键特征是问题的 B ;A、重叠子问题B、最优子结构性质C、贪心选择性质D、定义最优解42.采用贪心算法的最优装载问题的主要计算量在于将集装箱依其重量从小到大排序,故算法的时间复杂度为 B ;A 、On2nB 、OnlognC 、O2nD 、On43. 以深度优先方式系统搜索问题解的算法称为 D ;A 、分支界限算法B 、概率算法C 、贪心算法D 、回溯算法44. 实现最长公共子序列利用的算法是B ;A 、分治策略B 、动态规划法C 、贪心法D 、回溯法45. Hanoi 塔问题如下图所示;现要求将塔座A 上的的所有圆盘移到塔座B 上,并仍按同样顺序叠置;移动圆盘时遵守Hanoi 塔问题的移动规则;由此设计出解Hanoi 塔问题的递归算法正确的为:B46. 动态规划算法的基本要素为 CA. 最优子结构性质与贪心选择性质 B .重叠子问题性质与贪心选择性质C .最优子结构性质与重叠子问题性质 D. 预排序与递归调用 47. 能采用贪心算法求最优解的问题,一般具有的重要性质为: AA. 最优子结构性质与贪心选择性质 B .重叠子问题性质与贪心选择性质C .最优子结构性质与重叠子问题性质 D. 预排序与递归调用48. 回溯法在问题的解空间树中,按 D 策略,从根结点出发搜索解空间树;A.广度优先B. 活结点优先C.扩展结点优先D. 深度优先49. 分支限界法在问题的解空间树中,按 A 策略,从根结点出发搜索解空间树;A.广度优先B. 活结点优先C.扩展结点优先D. 深度优先50. 程序块 A 是回溯法中遍历排列树的算法框架程序;A.B. C. D. 51. 常见的两种分支限界法为DA. 广度优先分支限界法与深度优先分支限界法;B. 队列式FIFO 分支限界法与堆栈式分支限界法;C. 排列树法与子集树法;D. 队列式FIFO 分支限界法与优先队列式分支限界法;1.算法的复杂性有 时间 复杂性和 空间 ;2、程序是 算法用某种程序设计语言的具体实现;3、算法的“确定性”指的是组成算法的每条 指令 是清晰的,无歧义的;4. 矩阵连乘问题的算法可由 动态规划 设计实现;5、算法是指解决问题的 一种方法 或 一个过程 ;6、从分治法的一般设计模式可以看出,用它设计出的程序一般是 递归算法 ;7、问题的 最优子结构性质 是该问题可用动态规划算法或贪心算法求解的关键特征;8、以深度优先方式系统搜索问题解的算法称为 回溯法 ;9、计算一个算法时间复杂度通常可以计算 循环次数 、 基本操作的频率 或计算步; Hanoi 塔A. void hanoiint n, int A, int C, int B{ if n > 0{ hanoin-1,A,C, B;moven,a,b; hanoin-1, C, B, A; }} B. void hanoiint n, int A, int B, int C { if n > 0 { hanoin-1, A, C, B; moven,a,b; hanoin-1, C, B, A; } }C. void hanoiint n, int C, int B, int A { if n > 0 { hanoin-1, A, C, B; moven,a,b; hanoin-1, C, B, A; } }D. void hanoiint n, int C, int A, int B { if n > 0 { hanoin-1, A, C, B; moven,a,b; hanoin-1, C, B, A; } } void backtrack int t{ if t>n outputx; else for int i=t;i<=n;i++ { swapxt, xi; if legalt backtrackt+1; swapxt, xi; } } void backtrack int t { if t>n outputx;elsefor int i=0;i<=1;i++ { xt=i; if legalt backtrackt+1; } }void backtrack int t { if t>n outputx; else for int i=0;i<=1;i++ { xt=i; if legalt backtrackt-1; } }voidbacktrack int t{ if t>n outputx; else for int i=t;i<=n;i++ { swapxt, xi; if legalt backtrackt+1;}}10、解决0/1背包问题可以使用动态规划、回溯法和分支限界法,其中不需要排序的是动态规划 ,需要排序的是回溯法 ,分支限界法 ;11、使用回溯法进行状态空间树裁剪分支时一般有两个标准:约束条件和目标函数的界,N皇后问题和0/1背包问题正好是两种不同的类型,其中同时使用约束条件和目标函数的界进行裁剪的是 0/1背包问题 ,只使用约束条件进行裁剪的是 N皇后问题 ;12、贪心选择性质是贪心算法可行的第一个基本要素,也是贪心算法与动态规划算法的主要区别;13、矩阵连乘问题的算法可由动态规划设计实现;14.贪心算法的基本要素是贪心选择性质和最优子结构性质 ;15. 动态规划算法的基本思想是将待求解问题分解成若干子问题 ,先求解子问题 ,然后从这些子问题的解得到原问题的解;16.算法是由若干条指令组成的有穷序列,且要满足输入、输出、确定性和有限性四条性质;17、大整数乘积算法是用分治法来设计的;18、以广度优先或以最小耗费方式搜索问题解的算法称为分支限界法 ;19、贪心选择性质是贪心算法可行的第一个基本要素,也是贪心算法与动态规划算法的主要区别;20.快速排序算法是基于分治策略的一种排序算法;21.动态规划算法的两个基本要素是. 最优子结构性质和重叠子问题性质 ;22.回溯法是一种既带有系统性又带有跳跃性的搜索算法;23.分支限界法主要有队列式FIFO 分支限界法和优先队列式分支限界法;24.分支限界法是一种既带有系统性又带有跳跃性的搜索算法;25.回溯法搜索解空间树时,常用的两种剪枝函数为约束函数和限界函数 ;26.任何可用计算机求解的问题所需的时间都与其规模有关;27.快速排序算法的性能取决于划分的对称性 ;28.所谓贪心选择性质是指所求问题的整体最优解可以通过一系列局部最优的选择,即贪心选择来达到 ;29.所谓最优子结构性质是指问题的最优解包含了其子问题的最优解 ;30.回溯法是指具有限界函数的深度优先生成法 ;31.用回溯法解题的一个显着特征是在搜索过程中动态产生问题的解空间;在任何时刻,算法只保存从根结点到当前扩展结点的路径;如果解空间树中从根结点到叶结点的最长路径的长度为hn,则回溯法所需的计算空间通常为 Ohn ;32.回溯法的算法框架按照问题的解空间一般分为子集树算法框架与排列树算法框架;33.用回溯法解0/1背包问题时,该问题的解空间结构为子集树结构;34.用回溯法解批处理作业调度问题时,该问题的解空间结构为排列树结构;35.旅行售货员问题的解空间树是排列树 ;三、算法填空1.背包问题的贪心算法void Knapsackint n,float M,float v,float w,float x{//重量为w1..n,价值为v1..n的 n个物品,装入容量为M的背包//用贪心算法求最优解向量x1..nint i; Sortn,v,w;for i=1;i<=n;i++ xi=0;float c=M;for i=1;i<=n;i++{if wi>c break;xi=1;c-=wi;}if i<=n xi=c/wi;}2.最大子段和: 动态规划算法int MaxSumint n, int a{int sum=0, b=0; //sum存储当前最大的bj, b存储bjfor int j=1; j<=n; j++{ if b>0 b+= aj ;else b=ai; ; //一旦某个区段和为负,则从下一个位置累和 ifb>sum sum=b;}return sum;}3.贪心算法求活动安排问题template<class Type>void GreedySelector int n, Type s, Type f, bool A{A1=true;int j=1;for int i=2;i<=n;i++if si>=fj{ Ai=true;j=i;}else Ai=false;}4.快速排序template<class Type>void QuickSort Type a, int p, int r{if p<r{int q=Partitiona,p,r;QuickSort a,p,q-1; //对左半段排序QuickSort a,q+1,r; //对右半段排序}}5. 回溯法解迷宫问题迷宫用二维数组存储,用'H'表示墙,'O'表示通道int x1,y1,success=0; //出口点void MazePathint x,int y{//递归求解:求迷宫maze从入口x,y到出口x1,y1的一条路径mazexy=''; //路径置为if x==x1&&y==y1 success=1; //到出口则成功else{if mazexy+1=='O' MazePathx,++y;//东邻方格是通路,向东尝试if success&&mazex+1y=='O' MazePath++x,y;//不成功且南邻方格是通路,向南尝试if success&&mazexy-1=='O' MazePathx,--y;//不成功且西邻方格是通路,向西尝试if success&&mazex-1y=='O' MazePath--x,y;//不成功且北邻方格是通路,向北尝试}if success mazexy=''; //死胡同置为}四、算法设计题1. 给定已按升序排好序的n个元素a0:n-1,现要在这n个元素中找出一特定元素x,返回其在数组中的位置,如果未找到返回-1;写出二分搜索的算法,并分析其时间复杂度;template<class Type>int BinarySearchType a, const Type& x, int n{//在a0:n中搜索x,找到x时返回其在数组中的位置,否则返回-1Int left=0; int right=n-1;While left<=right{int middle=left+right/2;if x==amiddle return middle;if x>amiddle left=middle+1;else right=middle-1;}Return -1;}时间复杂性为Ologn2. 利用分治算法写出合并排序的算法,并分析其时间复杂度void MergeSortType a, int left, int right{if left<right {//至少有2个元素int i=left+right/2; //取中点mergeSorta, left, i;mergeSorta, i+1, right;mergea, b, left, i, right; //合并到数组bcopya, b, left, right; //复制回数组a}}算法在最坏情况下的时间复杂度为Onlogn;3.N皇后回溯法bool Queen::Placeint k{ //检查xk位置是否合法for int j=1;j<k;j++if absk-j==absxj-xk||xj==xk return false;return true;}void Queen::Backtrackint t{if t>n sum++;else for int i=1;i<=n;i++{xt=i;if 约束函数 Backtrackt+1;}}4.最大团问题void Clique::Backtrackint i // 计算最大团{ if i > n { // 到达叶结点for int j = 1; j <= n; j++ bestxj = xj;bestn = cn; return;}// 检查顶点 i 与当前团的连接int OK = 1;for int j = 1; j < i; j++if xj && aij == 0 // i与j不相连{OK = 0; break;}if OK { // 进入左子树xi = 1; cn++;Backtracki+1;xi = 0; cn--; }if cn+n-i>bestn { // 进入右子树xi = 0;Backtracki+1; }}5. 顺序表存储表示如下:typedef struct{RedType rMAXSIZE+1; //顺序表int length; //顺序表长度}SqList;编写对顺序表L进行快速排序的算法;int PartitionSqList &L,int low,int high //算法10.6b{//交换顺序表L中子表L.rlow..high的记录,枢轴记录到位,并返回其所在位置, //此时在它之前后的记录均不大小于它.int pivotkey;L.r0=L.rlow; //用子表的第一个记录作枢轴记录pivotkey=L.rlow.key; //枢轴记录关键字while low<high //从表的两端交替地向中间扫描{while low<high&&L.rhigh.key>=pivotkey --high;L.rlow=L.rhigh; //将比枢轴记录小的记录移到低端while low<high&&L.rlow.key<=pivotkey ++low;L.rhigh=L.rlow; //将比枢轴记录大的记录移到高端}L.rlow=L.r0; //枢轴记录到位return low; //返回枢轴位置}void QSortSqList &L,int low,int high{//对顺序表L中的子序列L.rlow..high作快速排序int pivotloc;if low<high //长度>1{pivotloc=PartitionL,low,high; //将L.rlow..high一分为二QSortL,low,pivotloc-1; //对低子表递归排序,pivotloc是枢轴位置 QSortL,pivotloc+1,high; //对高子表递归排序}}void QuickSortSqList &L{//对顺序表L作快速排序QSortL,1,L.length; }。
数据结构求解汉诺塔问题的递归算法

数据结构求解汉诺塔问题的递归算法汉诺塔问题是一个经典的数学问题,它可以通过递归算法来求解。
在这个问题中,我们需要将一堆盘子从一个柱子移动到另一个柱子,同时遵守以下规则:一次只能移动一个盘子,大盘子不能放在小盘子上面。
为了解决这个问题,我们可以使用数据结构中的栈来模拟柱子的堆叠。
我们可以将每个柱子表示为一个栈,每个盘子表示为一个元素。
初始时,所有的盘子都在第一个柱子上,我们需要将它们移动到第三个柱子上。
下面是求解汉诺塔问题的递归算法的伪代码:```1. 定义一个函数hanoi,接受参数n、起始柱子A、辅助柱子B、目标柱子C2. 如果n等于1,则直接将盘子从A移动到C3. 否则,将n-1个盘子从A移动到B,借助C作为辅助柱子4. 将第n个盘子从A移动到C5. 将n-1个盘子从B移动到C,借助A作为辅助柱子```接下来,我们来详细解释一下这个算法。
首先,我们定义了一个函数hanoi,它接受四个参数:n表示盘子的数量,起始柱子A、辅助柱子B和目标柱子C。
在函数内部,我们首先判断如果n等于1,那么我们直接将盘子从A移动到C即可。
这是递归算法的终止条件。
如果n大于1,我们需要将n-1个盘子从A移动到B,借助C作为辅助柱子。
这一步是通过递归调用hanoi函数来实现的。
在递归调用中,我们将n-1作为新的盘子数量,A作为起始柱子,B作为目标柱子,C作为辅助柱子。
接下来,我们将第n个盘子从A移动到C。
这一步是直接操作的,不需要递归调用。
最后,我们需要将n-1个盘子从B移动到C,借助A作为辅助柱子。
同样地,我们通过递归调用hanoi函数来实现这一步。
在递归调用中,我们将n-1作为新的盘子数量,B作为起始柱子,C作为目标柱子,A作为辅助柱子。
通过这样的递归调用,我们可以将所有的盘子从起始柱子A移动到目标柱子C,同时遵守汉诺塔问题的规则。
总结起来,数据结构中的栈可以很好地模拟汉诺塔问题中的柱子堆叠,而递归算法则可以很好地解决这个问题。
【算法】汉诺塔问题

【算法】汉诺塔问题汉诺塔问题是⼀个经典的问题。
汉诺塔(Hanoi Tower),⼜称河内塔,源于印度⼀个古⽼传说。
⼤梵天创造世界的时候做了三根⾦刚⽯柱⼦,在⼀根柱⼦上从下往上按照⼤⼩顺序摞着64⽚黄⾦圆盘。
⼤梵天命令婆罗门把圆盘从下⾯开始按⼤⼩顺序重新摆放在另⼀根柱⼦上。
并且规定,任何时候,在⼩圆盘上都不能放⼤圆盘,且在三根柱⼦之间⼀次只能移动⼀个圆盘。
问应该如何操作?当只有⼀个盘⼦时这是最简单的情况:只需将1号盘⼦从X塔移动到Z塔就OK于是我们可以写出如下的函数,来模拟完成这个过程。
假设盘⼦是⽤1,2,3...按照⼤⼩编码代表的,⽽塔则是⽤⼀个字符char表⽰的。
//将编号为 number 的盘⼦从 from 塔座移到 to 塔座void move(int number , char from , char to){std::cout<<"move dish "<<number<<": "<<from<<"--->"<<to<<std::endl;}有两个盘⼦时有2个盘⼦,⽬标是:将X塔上的盘⼦借助Y移动到Z盘⼦上。
特别的,为了好描述,我把X塔叫做源塔,因为盘⼦起初在这个塔上,把Y塔叫做辅助塔,因为Y塔只是起个过渡作⽤。
把Z盘叫做⽬标塔,最后所以的盘⼦都在这个塔上。
我们可以写出伪代码move(1,X,Y);move(2,X,Z);move(1,Y,Z);有三个盘⼦时在盘⼦数⼤于2的时候,⽆论有多少个盘⼦,我们眼⾥只有2个盘⼦:即最底层的最⼤的盘⼦,和它上⾯的所有盘⼦组和形成的⼀个盘,我们可以把它看做是2.5号盘。
这样考虑的好处是:⽆论有多少盘⼦,都可以⽤2个盘⼦的思路去做。
简化了思路。
因此,步骤是:1、将2.5号盘借助Z塔移动到Y塔上。
注意,处理这步操作时,X是源塔,Z是辅助塔,Y是⽬标塔2、将3盘移动到Z塔上,3、将2.5盘借助X塔移动到Z塔上。
著名算法matlab编程 贪心算法 背包问题 递归算法 Hanoi塔问题 回溯算法 n皇后问题

10/22
在命令窗口输入:>> [n,s]=hanoi(3,1,2,3) n= 7 s= 1 2 1 3 1 2 1 1 1 3 1 2 2 1 3 2 2 3 1 3 3
1
1 2 3
2 3 3 3 1
2
3
1
2 1 2
1
1 2
2
3
3
1
2 3
1 2 3
11/22
5/22
A
B
C
1
2
n
6/22
问题分析: 把柱C作为目标柱子,设an为n块金片从其中一柱移 到另一柱的搬运次数,则把n块金片从A移到C,可 以先把前n-1片移到B,需搬an-1次;接着把第n片从 A称到C,再从B把剩下的n-1片搬到C,又需搬an-1 次。所以从A到n块金片称到柱C,共需次数为: 2an-1+1次。 显然,当n=1时,a1=1,所以Hanoi塔的移动次数相 当于一个带初值的递归关系:
有 旅 行 者 要 从 n 种 物 品 中 选 取 不 超 过 b公 斤 的 物 品 放 入 背 包 , 要 求 总 价 值 最 大 。 设 第 i 种 物 品 的 重 量 为 a i, 价 值 为 c i,i 1, 2 , n )。 定 义 向 量 [ x 1 , x 2 , , x n ], 当 选 第 i ( 种 物 品 往 背 包 放 时 取 x i 1, 否 则 取 x i 0。 于 是 所 有 选 取 的 物 品 的 总 价 值 为 : c 1 x 1 c 2 x 2 c n x n, 总 的 重 量 为 : a 1 x 1 a 2 x 2 a n x n。 问 题 可 描 述 为
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
第6章函数——Hanoi塔问题的递归求解
什么情况下考虑使用递归?
通常下面三种情况需要使用递归:
数学定义是递归的
如计算阶乘,最大公约数和Fibonacci数列 数据结构是递归的
如队列、链表、树和图
问题的解法是递归的
如Hanoi塔,骑士游历、八皇后问题(回溯法)
汉诺塔(Hanoi )问题
印度神话,上帝创造世界时作了三根金刚石柱子,第一根上从下往上按
大小顺序摞着64片黄金圆盘,上帝命令婆罗门把圆盘从下开始按大小顺序重新摆放到第二根上,规定每次只能移动一个圆盘,在小圆盘上不能放大圆盘
当n=64时,需移动多少次呢?
18446744073709551615,即1844亿亿次
若按每次耗时1微秒计算,则64个圆盘的移动需60万年一个经典的递归问题
汉诺塔(Hanoi )问题
较为简单的情形——n =2
将1号圆盘从A 移到C
将2号圆盘从A 移到B 将1号圆盘从C 移到B
A C
汉诺塔问题的递归求解
✓将C移到B ⏹将“上面n-1个圆盘”看成一个整体
将“上面n-1个圆盘”从C 移到B
✓将“n 个圆盘”借助于C 从A 移到B
✓将“n个圆盘”借助于C从A移到B
讨论
汉诺塔问题可以用非递归的方法求解吗?。