汉诺塔(总结)

#include <stdio.h>
 
/**
*递归处理汉诺塔
*/
void hanoi(int paraN, char paraSource, char paraDestination, char paraTransit)
{
	if (paraN == 0) return;
	else
	{
		hanoi(paraN - 1, paraSource, paraTransit, paraDestination);
		printf("%c -> %c\n", paraSource, paraDestination);
		printf("%p -> %p\n", &paraSource, &paraDestination);
		hanoi(paraN - 1, paraTransit, paraDestination, paraSource);
	}
}
 
/**
*测试函数,使用两个例子进行测试。将三根柱子设为a,b,c。
*/
void hanoiTest()
{
	printf("--- addToTest begins. ---\n");
 
	printf("2 plates\n");
	hanoi(2, 'A', 'B', 'C');
 
	printf("3 plates\n");
	hanoi(3, 'A', 'B', 'C');
 
	printf("---- addToTest ends. ---\n");
}
 
void main()
{
	hanoiTest();
}

一、自顶向下,逐渐求精,函数调用

        我们要将S杆上的N个圆盘移动至D杆上,首先我们可以考虑到先试着用移动两个圆盘或者三个圆盘的简单情况来分析。通过分析后发现,要将N个圆盘从S杆移动到D杆,实质上就是先将S杆上的N-1个圆盘以D杆为辅助移动至T杆,然后将第N个圆盘直接移动至D杆,最后再将T杆上的N-1个圆盘以S杆为辅助移动至D杆,这样,我们就解决了这个问题。因此我们可以设计一个函数hanoi(int paraN, char paraSource, char paraDestination, char paraTransit)来表示此过程,其中paraN表示圆盘的个数,paraSource是起始杆,paraDestination是目标杆,paraTransit是中间杆。

二、递归与分治

        通过第一步的分析,当我们以D杆为中介时,将S杆上N-1个圆盘都移到杆T杆上,本身就为一个n-1的汉诺塔问题了,此时的起始杆是S杆,目标杆为T杆,再将S杆上第N个圆盘移动到D上;同样,以S杆为中介,将T杆上的N-1个圆盘移动到D杆上时,其本身也就为一个n-1的汉诺塔问题了,此时的起始杆为T杆,目标杆为D杆。

三、不要跨层分析

        当移动N-1个圆盘时,我们不要逐个逐个地去考虑其中某一个圆盘是怎么移动的,其本质上还是将N-1个圆盘从起始杆移动至目标杆。因此,我们只需要认为这是一个N-1的汉诺塔问题,再次调用hanoi()函数,计算机会为我们解决此过程。

四、形参与实参

        在函数调用过程中,我们使用形参来表示函数的输入参数,而实参则是在函数调用时提供的具体数值。在汉诺塔问题中,形参paraN表示圆盘的个数,paraSource表示起始杆,paraDestination表示目标杆,paraTransit表示中间杆。在我们调用函数时,我们需要提供实践的圆盘个数和三个杆的具体名称,如hanoi(3 , 'S' , 'D' , 'T')。

五、有意义规范的标识符

        在编写程序时,使用有意义、规范的标识符可以使代码更易于理解和维护。在汉诺塔问题中,形参变量名paraN、paraSource、paraDestination、paraTransmit和函数名hanoi,我们可以通过英文意思清晰了解到它们每一个的作用,这些标识符可以更好地表达程序的含义,并提高代码的可读性。

六、时间复杂度

       当 n=1时,移动步骤是1步,n=2时,移动步骤是3步,n=3时,移动步骤是7步,通过归纳法我们可以得到当有n个盘子时,移动次数时2^n-1,所以时间复杂度是O(2^n).。

七、递归栈

        由于计算机在执行指令时,一次只能执行一条,所以计算机在执行指令时运用了栈结构。先进栈的指令被压在栈最底部执行,后读取的指令依次入栈,当读取到执行指令时再执行栈顶的指令。所以当调用hanoi函数时,递归函数将前面的所有调用全部压栈,当最底层调用结束后,开始读取执行指令,从栈顶指令开始执行,将结果返回下一层函数。

八、空间复杂度

        无论上面说的多花,在整个递归过程中,由于栈的出战与压栈,有多少层,我们栈就压几层所以空间复杂度为O(n).

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值