java汉诺塔非递归_汉诺塔的非递归算法

本文介绍了如何将汉诺塔的递归算法转化为非递归算法,通过模拟递归过程,利用堆栈保存调用现场。详细阐述了处理首递归、尾递归的过程,并给出了完整的Java源代码实现。
摘要由CSDN通过智能技术生成

思路

模拟递归程序执行过程,借助一个堆栈,把递归转成非递归算法。

转化过程

1. 递归算法

1 void hanoi(int n, char from, char pass, charto) {2 if (n == 0)3 return;4

5 hanoi(n - 1, from, to, pass);6 move(n, from, to);7 hanoi(n - 1, pass, from, to);8 }

2. 处理首递归

本函数第2行是结束条件,第5行开始进入首递归。执行第5行函数调用之前,需要保留调用现场,本例中是4个参数入栈,使用新的参数调用hanoi函数。而继续跟踪被调用的函数,可以看出需要一直进行入栈操作,直到参数n == 0为止。 对此行为,我们可以用一个循环来模拟:

伪代码:

int i =n;while (i != 0) {

push(i); i --;}

现在可以断言 i ==0 ,满足函数返回的条件。当函数返回后,需要通过pop操作来恢复现场,然后继续执行后面的语句。为了简化问题,我们假设后面只有move()一条语句,执行完毕该语句后就继续向上一层回溯,直至最顶层, 这样又可以用一个循环来模拟:

伪代码:int i =n;while (i != 0) {

push(i);

i--;

}while(栈不空) {int m =pop();

move(m, ...);

尾递归...

}

3. 处理尾递归

一般而言,尾递归可以直接改成上一条语句的循环。但在本例中,尾递归被嵌在另一个循环中,此时需要模拟它的行为:进入尾递归hanoi()函数后,需要执行其函数体,而函数体又是上述代码中的第一句话,可以如下表示:

伪代码:

a_new_beginning:int i =n;while (i != 0) {

push(i);

i--;

}while(栈不空) {int m =pop();

move(m, ...);

产生新的参数,跳出循环,跳转到a_new_beginning语句处;

}

相比于第一个while全部执行,第二个while实际只被执行一次就跳出来了,这种结构,很显然可以等价变换为外加一个大循环。那么在外部的大循环的作用下,第二个while循环可以“降维”, 去掉一层循环, 并根据pop()的现场来产生新的一批参数,给下一次循环使用。注意,两层循环合并后,循环终止条件也需要进行合并。

伪代码:while (!(n == 0 &&栈空)) // 内外两层终止条件进行合并int i =n;while (i != 0) {

push(i);

i--;

}int m =pop();

move(m, ...);//产生新的参数

n =m;

n--; //对应hanoi(n - 1, pass, ...)

}

最后进行完善,加上其他参数的变换。

源代码

#include #include

using namespacestd;void move(int n, char from, charto) {

cout<< "from" << from << "move" << n << "to" << to <

}structparam {intn;char from;charpass;charto;

};void hanoi(int n, char from, char pass, charto) {

stacks;

param par_outer= {n, from, pass, to};while (!(par_outer.n == 0 &&s.empty())) {

param par_inner=par_outer;while (par_inner.n > 0) {

s.push(par_inner);

par_inner.n--;

swap(par_inner.pass, par_inner.to);

}

par_outer=s.top();

s.pop();

move(par_outer.n, par_outer.from, par_outer.to);

par_outer.n--;

swap(par_outer.from, par_outer.pass);

}

}intmain() {int N = 5;

hanoi(N,'A', 'B', 'C');return 0;

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值