汉诺塔问题——分而治之(引入递归,解决重复子问题)
Posted higer-TSW
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了汉诺塔问题——分而治之(引入递归,解决重复子问题)相关的知识,希望对你有一定的参考价值。
汉诺塔问题的引入:
相传在古印度圣庙中,有一种被称为汉诺塔(Hanoi)的游戏。该游戏是在一块铜板装置上,有三根杆(编号A、B、C),在A杆自下而上、由大到小按顺序放置64个金盘(如图1)。游戏的目标:把A杆上的金盘全部移到C杆上,并仍保持原有顺序叠好。操作规则:每次只能移动一个盘子,并且在移动过程中三根杆上都始终保持大盘在下,小盘在上,操作过程中盘子可以置于A、B、C任一杆上。 (ps:来自于百度)
1.求解思路:
假设只有一层塔,那么就只需要将a移动到c即可;
假设有二层塔,需要先将前一个小圆盘从a移动到b,再将最后大圆盘1个移动到c,再将b中的小圆盘从b移动到c;
假设有三层塔,需要先将前两个小圆盘从a移动到b,再将最后大圆盘1个移动到c,再将b中的小圆盘从b移动到c;
……
假设有n-1层塔,需要先将前n-2个小圆盘从a移动到b,再将最后大圆盘1个移动到c,再将b中的小圆盘从b移动到c;
假设有n层塔,需要先将前n-1个小圆盘从a移动到b,再将最后大圆盘1个移动到c,再将b中的小圆盘从b移动到c;
由上述观察可知:求解第二层塔与第n层塔的解题步骤是一致的,求解第n层塔需要求解第n-1层塔;求解第n-1层塔需要求解第n-2层塔………求解第三层塔需要求解第二层2塔,可以将其看成一个等比数列,每次的都需要比上一次多进行一倍操作,由等比数列求和公式得,总共进行了2^n-1次移动,所以时间复杂度为O(2^n)!
2.如何求解:
从上述不难看出,每次求解的步骤都一样,那有没有有什么方法解决重复的问题呢?
————递归会给你答案
什么是递归:递归算法(英语:recursion algorithm)在计算机科学中是指一种通过重复将问题分解为同类的子问题而解决问题的方法。递归式方法可以被用于解决很多的计算机科学问题,因此它是计算机科学中十分重要的一个概念。绝大多数编程语言支持函数的自调用,在这些语言中函数可以通过调用自身来进行递归。计算理论可以证明递归的作用可以完全取代循环,因此在很多函数编程语言(如Scheme)中习惯用递归来实现循环。(ps:来自于百度)
递归实际上就是一种自调用函数,自己调用自己,从而达到解决重复步骤的问题;
如果汉诺塔只有一层的时候我们就需要把a移动到c
如果2层以上呢:由于递归函数再求解过程中不会改变步骤,每次都是固定从a移动到c,所以我们要将每根柱子做一个标记,方便理解交换时所带来的里面元素的改变过程;设:
第一个柱子为交换柱子:需要移动的元素都放在第一个位置
第二个柱子为中间柱子:不需要移动元素放在第二个柱子里
第三个柱子为目标柱:将要移动的元素放到第三个柱子
现在递归循环是从第二层到第n层开始的:
1.从上一层结束开始c元素在目标柱中,所以需要交换到目标柱当中(c元素)
2.将a移动到b,所以a元素在交换柱,b元素在目标柱
3.然后将b移动到c,b为交换柱,c为目标柱,a在中间柱子
3.代码实现
void Hannouta(int n, char pos1, char pos2, char pos3) if (n == 1) move(n, pos1, pos3);//move为交换函数 else Hannouta(n-1, pos1, pos3, pos2); move(n, pos1, pos3); printf("盘子%d: 从 %c柱 移动到 %c柱\\n", n, pos1, pos3); Hannouta(n-1, pos2, pos1, pos3);
4.时间复杂度分析
由上述分析可知道——时间复杂度为O(2^n);
以上是关于汉诺塔问题——分而治之(引入递归,解决重复子问题)的主要内容,如果未能解决你的问题,请参考以下文章