汉诺塔 栈

#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();
}

要想将N个方块从A移动到C,就要

①将N-1个方块从A移动到B(利用递归解决这一步);

②将方块”N“从A移动到C(因为此时N上方的方块全在B柱子上,由于步骤①的实现,方块N可以再A和C之间畅通无阻);

③将剩余的N-1个方块从B移动到N的上方,也就是将N-1个方块从B移动到C(如何实现这一步?这一步不就是和步骤①一模一样吗?)

分析:

1、自顶向下,逐项求精

汉诺塔问题需要运用到递归的方法来解决,递归就是要将问题分解为规模较小但类型相同的子问题。自顶向下可以看作一颗递归树,第一层一个节点,下面按2的倍数增加。最后这些解合并起来就是问题最终的解。

2、递归,分治

分治法是一种较为常用的算法。它是指将问题分解为规模较小的子问题,通过递归的方式进行分治。分治法需要注意划分的范围。而递归需要注意递归函数的出口与边界条件。汉诺塔问题就需要使用递归与分治的思想。出口函数一般设置为n=1的时候。

3、形参与实参

用通俗的话来讲,形参相当于占一个坑,告诉这个函数有哪些坑在调用的时候需要填上。而实参就是我们需要实际解决问题的大小。

4、有意义、规范的标识符

有意义、规范的标识符一般用英文单词的缩写或是i,j此类为大部分人所熟知的迭代标识符。可以提高代码的可读性。

5、时间复杂度

虽然递归调用时我们对其进行了分治,但是子问题的总规模不变,所以递归树的每一层总的时间都为2cn,是按2的倍数递增,所以时间复杂度为o(2^n)。

6、递归栈

计算机在执行指令时,一次只能执行一条指令,所以,需要用到栈的结构。简单来说就是先将指令入栈,在递归到不能再向下分解时,开始执行指令,即将栈顶指令出栈。

7、空间复杂度

由于在递归过程中,我们需要使用一个递归栈来保存每个递归调用的状态。因为递归栈的深度等于递归调用的层数,所以空间复杂度为 O(n)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值