我正在学习c ++中的递归,但是被以下用于解决河内塔问题的c ++代码所困扰。
void Hanoi(int m, string start, string middle, string end){
cout << "m is equal to: " << m << endl;
if(m == 1){
cout << "Move Disc " << " from " << start << " to " << end << endl;
}
else{
Hanoi(m-1,start,end,middle);
cout << "Move disc " << m << " from " << start << " to " << end << endl;
Hanoi(m-1,middle,start,end);
}
}
int main(){
int discs = 3;
Hanoi(discs, "start","middle","end");
}
代码输出如下:
m is equal to: 3
m is equal to: 2
m is equal to: 1
Move Disc from start to end
Move disc 2 from start to middle
m is equal to: 1
Move Disc from end to middle
Move disc 3 from start to end
m is equal to: 2
m is equal to: 1
Move Disc from middle to start
Move disc 2 from middle to end
m is equal to: 1
Move Disc from start to end
我的一般问题是我不了解递归的工作方式。为什么在执行“ if”语句之前将m设为1? m如何回到2?
答案 0 :(得分:3)
如果将其打印为树状,则会得到以下内容:
main
|--> hanoi(3, ...)
| |
| |--> hanoi(2, ...)
| | |
| | |--> hanoi(1, ...)
| | |--> hanoi(1, ...)
| |<----|
| |--> hanoi(2, ...)
| | |
| | |--> hanoi(1, ...)
| | |--> hanoi(1, ...)
| |<----|
|<-----|
|
对于每次对hanoi(m, ...)
的调用,除非m == 1,它将两次继续调用hanoi(m-1,...)。在第一次调用中,它将再次调用hanoi(m-1,..)。 。)直到m为1。
因此,当m为2时向后走,它将连续两次调用hanoi(1,...):
hanoi(2, ...)
hanoi(1, ...)
hanoi(1, ...)
当m为3时,它将连续两次调用hanoi(2,...),因此:
hanoi(3, ...)
hanoi(2, ...)
hanoi(1, ...)
hanoi(1, ...)
hanoi(2, ...)
hanoi(1, ...)
hanoi(1, ...)
答案 1 :(得分:0)
让我们从输出的第一部分开始:
m is equal to: 3
m is equal to: 2
m is equal to: 1
首先像这样调用Hanoi
函数:Hanoi(3)
。
由于在这种情况下是m != 1
,因此我们将再次调用Hanoi(m-1)
。这将产生上面的输出。现在,我们在此功能上深入了3个级别。
自m == 1
起,我们现在将看到以下输出:
Move Disc from start to end
。
现在,我们退出最深的函数,并弹出回到函数调用堆栈的2级。现在我们输出:
Move disc 2 from start to middle
。
答案 2 :(得分:-1)
此跟踪应该可以为您提供帮助,如果没有,那么您始终可以通过谷歌搜索“河内塔递归程序跟踪”来找到更多跟踪
您还可以在https://javabypatel.blogspot.com/2015/12/tower-of-hanoi.html
找到该算法的工作原理答案 3 :(得分:-1)
您的目标是将所有磁盘移动到另一个位置。
要解决这个难题,您需要将塔从位置1移动到位置2。
为此,您需要将最大的磁盘从位置1移动到位置2。
为此,位置2必须为空,所有其他磁盘都必须位于位置3(大小为m-1的塔)。
因此,您需要解决m-1大小的难题(将m-1大小的塔从位置1移到3)。这是第一个递归调用。
现在,您可以将最大的磁盘从位置1移动到位置2。 这是递归函数调用之间的输出。
现在您需要将大小为m-1的塔从位置3移动到位置2。
因此,您需要再次解决m-1大小的难题(将m-1大小的塔从位置3移到2)。这是第二个递归函数调用。
如果没有这种递归,唯一可以解决的问题是将大小为1的塔移动到另一个地方,因为顶部没有任何磁盘,而您也可以移到其他任何磁盘的顶部。这就是在执行if语句之前m必须为1的原因。