汉诺塔问题 最简单的图文讲解递归实现
问题简化:
假设有 A,B,C三个柱子。有n个盘子,从大到小依次放在A柱上,我们目标是把A柱的盘子移到C柱。遵循如下原则:
1.小盘的上面不能放大圆盘。
2.在三根柱子之间一回只能移动一个圆盘。
3.只能移动在最顶端的圆盘。
解法介绍
在理解递归时,难点就像小学生理解方程一样,无法理解将未知的设置为x,假设它为已知的方式求解。递归也一样,我们将某个函数通过定义,假设它能实现这个功能,并且在函数内部又肯定会依赖于这个功能,会发生自己调用自己的情况。比如我们这里的功能机为:
tower(int n, string from, string to, string tmp)
这个功能机能实现将n个盘子,从源柱from,利用临时柱tmp,最终将盘子移动到目标柱to上。
它既然能将n个盘子搬过去,那一定也能将n-1个盘子搬过去。这就是递归的精髓。递归的出口就是当只有一个时,直接搬过去就行。
思路与源码:
这三个柱子在变换着充当源柱,目标柱,临时柱。
1)如果只有一个盘子时,直接从源柱到目标柱(对应代码标记A部分)。
2) 否则就把所有上面的n-1个盘子,先从源柱移到临时柱上(B部分)。再把第n个从源柱到目标柱(C部分)。最后把n-1个盘子从临时柱到目标柱(D部分)。这里和移动两个盘子的思路是一样的。
void tower(int n, string from, string to, string tmp) { if (n == 1) { cout << n << from << " to " << to << endl; //A } else { tower(n - 1, from, tmp, to); //B cout << n << from << " to " << to << endl; //C tower(n - 1, tmp, to, from); //D } } int main(int argc, char** argv) { tower(7, " A ", " C ", " B "); }