Hanoi塔問題

递归调

  一 的函 自身 为递归调 用。 这种 数称 为递归 。C 言允 递归调 用。在 递归调 用中, 又是被 递归 数将 复调 用其自身。 用一次就 入新的一 。例如有函 f 如下:
int f (int x)
{
int y;
z=f(y);
return z;
}
   是一 递归 但是 数将 无休止地 用其自身, 然是不正确的。 了防止 递归调 用无 止地 行, 在函 数内 递归调 用的手段。常用的 法是加 件判 足某 件后就不再作 递归调 用,然后逐 返回。 下面 递归调 用的 程。
[例5.9]用
递归 n!用 递归 n!可用下述公式表示:
n!=1 (n=0,1)
n×(n-1)! (n>1)
按公式可
程如下:

long ff(int n)
{
long f;
if(n<0) printf("n<0,input error");
else if(n==0||n==1) f=1;
else f=ff(n-1)*n;
return(f);
}
程序中
出的函 ff是一 递归 主函 ff 后即 入函 ff 行,如果 n<0,n==0 n=1 束函 行,否 递归调 ff 自身。由于 递归调 用的 n-1 ,即把 n-1 值赋 予形 n ,最后 n-1 值为 1 再作 递归调 用,形 n 1 使 递归终 止。然后可逐 退回。下面我 该过 程。 设执 行本程序 时输 5 , 即求 5! 。在主函 中的 句即 y=ff(5) ff 后,由于 n=5, 不等于 0 1 ,故 应执 f=ff(n-1)*n, f=ff(5-1)*5 该语 ff 递归调 用即 ff(4) 。 逐次 递归 5.3 所示。 行四次 递归调 用后, ff 取得的 值变为 1 ,故不再 继续递归调 用而 始逐 返回主 ff(1) 的函 返回 值为 1 ff(2) 的返回 值为 1*2=2 ff(3) 的返回 值为 2*3=6 ff(4) 的返
值为 6*4=24 ,最后返回 ff(5) 24*5=120

  例 5. 9 也可以不用 递归 的方法 完成。如可以用 推法,即 1 始乘以 2 ,再乘以 3… 直到 n 推法比 递归 法更容易理解和 实现 。但是有些 问题则 只能用 递归 算法才能 实现 。典型的 问题 Hanoi 问题
  
   [ 5.10]Hanoi 问题
板上有三根 A B C A 上套有 64 大小不等的 圆盘 大的在下,小的在上。如 5.4 所示。要把 64 圆盘 A C 上, 次只能移 圆盘 ,移 可以借助 B 针进 行。但在任何 候,任何 上的 圆盘 都必 保持大 在下,小 在上。求移
算法分析如下, A 上有 n 子。
如果n=1, 圆盘 A直接移 C。
.3
如果 n=2
1.
A 上的 n-1( 等于 1) 圆盘 移到 B 上;
2.
A 上的一 圆盘 移到 C 上;
3.
最后 B 上的 n-1( 等于 1) 圆盘 移到 C 上。
如果 n=3
A.
A 上的 n-1( 等于 2 ,令其 n`) 圆盘 移到 B( 借助于 C)
如下:
(1)
A 上的 n`-1( 等于 1) 圆盘 移到 C 上, 见图 5.5(b)
(2)
A 上的一 圆盘 移到 B 见图 5.5(c)
(3)
C 上的 n`-1( 等于 1) 圆盘 移到 B 见图 5.5(d)
B.
A 上的一 圆盘 移到 C 见图 5.5(e)
C.
B 上的 n-1( 等于 2 ,令其 n`) 圆盘 移到 C( 借助 A)
如下:
(1)
B 上的 n`-1( 等于 1) 圆盘 移到 A 见图 5.5(f)
(2)
B 上的一 子移到 C 见图 5.5(g)
(3)
A 上的 n`-1( 等于 1) 圆盘 移到 C 见图 5.5(h)
到此,完成了三 圆盘 的移 动过 程。
上面分析可以看出, n 大于等于 2 程可分解

第一 A 上的 n-1 圆盘 移到 B 上;
第二 A 上的一 圆盘 移到 C 上;
第三 B 上的 n-1 圆盘 移到 C 上;其中第一 和第三 同的。
n=3 ,第一 和第三 又分解 为类 同的三 ,即把 n`-1 圆盘 移到另一 上, 里的 n`=n-1 是一 递归过
程,据此算法可
程如下:
move(int n,int x,int y,int z)
{
if(n==1)
printf("%c-->%c/n",x,z);
else
{
move(n-1,x,z,y);
printf("%c-->%c/n",x,z);
move(n-1,y,x,z);
}
}
main()
{
int h;
printf("/ninput number:/n");
scanf("%d",&h);
printf("the step to moving %2d diskes:/n",h);
move(h,'a','b','c');
}
move(int n,int x,int y,int z)
{
if(n==1)
printf("%-->%c/n",x,z);
else
{
move(n-1,x,z,y);
printf("%c-->%c/n",x,z);
move(n-1,y,x,z);
}
}
main()
{ ……
move(h,'a','b','c');
}
  
程序中可以看出,move函 是一 递归 有四 n,x,y,z。 n 表示 圆盘 x,y,z 表示三根 move 的功能是把 x 上的 n 圆盘 z 上。 n==1 ,直接把 x 上的 圆盘 移至 z 上, x→z 。如 n!=1 递归调 move ,把 n-1 圆盘 x 移到 y x→z 递归调 move ,把 n-1 圆盘 y 移到 z 。在 递归调 程中 n=n-1 ,故 n 逐次 ,最后 n=1 递归 ,逐 返回。 n=4 程序 行的
input number:
4
the step to moving 4 diskes:
a→b
a→c
b→c
a→b
c→a
c→b
a→b
a→c
b→c
b→a
c→a
b→c
a→b
a→c
b→c
 在 实际问题 中,一 据往往具有不同的 。例如, 在 生登 表中,姓名 应为 字符型; 学号 整型或字符型; 龄应为 整型;性 别应为 字符型;成 整型或 型。 然不能用一 个数 存放 据。 中各元素的 型和 度都 一致,以便于 编译 统处 理。 了解 问题 ,C 言中 出了另一 ——“ 于其 级语 言中的 记录
 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值