汉诺塔问题:

有三根竖着的木棍,其中一根木棍上串着N个自下而上逐渐变小的圆盘,现在要求将N个盘子从A木棍移动到C木棍上,且满足以下两个条件:

1.无论何时,任何圆盘上方不能有比他更大的圆盘

2.一次只能移动一个圆盘

问:如何移动才能达到要求?

 

解题步骤:

假设要移动n个单位, 起始点是A, 目标地点是C, 中间点是B

那么问题可以分为以下步骤:

step 1:n-1个单位由 A 移动到 B

step 2:1个单位由 A 移动到 C

step 3:n-1个单位由 B 移动到 C

其中step 1 和 step 2 又可以拆分为这三个步骤,直到只有一个单位

那么问题的算法就出来了:

循环体:step1 step2 step3

终止条件:直到只有一个单位

//递归
void move(char A, char B, char C, int Ahigh)
{
    if(Ahigh == 1)//结束条件
        step(A,C);
    else//循环体
    {
        move(A,C,B,Ahigh-1);
        step(A,C);
        move(B,A,C,Ahigh-1);    
    }
}

*step函数的功能是将 A->C 打印在控制台上

 

解题思考:

很能体现递归思想的汉诺塔问题,当一个复杂的问题,可以拆分为有一定规律的步骤时,便可以使用递归的方法来解决

实际上递归也是一种循环,笔者认为,凡是可以使用递归解决的问题,循环都可以做到,递归的优缺点也比较明显:

递归:

优点:可以更加清晰的表达自己的思路,让自己的程序变得更加美观;

缺点:我们知道,递归是在不断的调用自身,也就是不断地在调用一个函数,而当一段程序在进入某一个函数时,都要做一件事:保存返回地址和现场,通常是以压栈的形式进行,而这样做就会增加程序运行时额外的开销,对于一些深层的递归,还可能导致栈溢出。

综上所述:

通过权衡时间效益和代码可读性,选择合适的算法作为最终的目标;