递归算法以及Hanoi(汉诺)塔问题及其详细解释

递归在算法中是非常重要的,可以说几乎所有的循环算法都可以用递归来实现,这足以体现递归的重要性,利用递归的条件一般为一下:

  1. 定义是递归的

像有些数学函数就是递归定义的,例如大家熟悉的阶层函数;

    2.利用“分治法”

  • 2.1 对于复杂问题,若能够分成几个相对简单却算法相同或类似的子问题来求解便可使用递归算法。
  • 2.2 能将一个问题转变成一个新问题,而新闻体育原问题的解法相同或类同,不同的仅是处理的对象,并且这些处理对象更小却变化有规律。
  • 2.3 可以通过上述转化使问题简单化
  • 2.4 必须有一个明确的递归出口,或称递归的边界

在数据结构中有些数据结构是递归的,这又怎么理解呢?

如, 对于链表,其结点 LNode 的定义由数据域 data 和指针域 next 组成, 而指针域 next 是一种
指向 LNode 类型的指针, 即 LNode 的定义中又用到了其自身, 所以链表是一种递归的数据结构。
对于递归的数据结构, 相应算法采用递归的方法来实现特别方便。链表的创建和链表结点的 .
遍历输出都可以采用递归的方法。算法 3.9 是从前向后遍历输出链表结点的递归算法, 调用此递
归函数前,参数 p 指向单链表的首元结点,在递归过程中,p 不断指向后继结点,直到 p 为 NULL
时递归结束。显然, 这个问题满足上述给出的采用 “分治法” 进行递归求解的问题需要满足的三
个条件

代码如下:

void TraverseList(LinkList p)
{
if(p==NULL) return;//递归终止
else
{
cout<<p->data<<end;
TraverseList(p->next);
}
}

本次主要讲一下hanoi塔算法

问题规则:Hanoi(汉诺)塔问题。古代有一个焚塔,塔内有3个座A,B,C,开始时A座上有64个盘子,盘子大小不等,大的在上,小的在下,有一个老和尚想把这64个盘子从A座移到C座,但规定每次只允许移到一个盘,且在移动过程中在3个座上都始终保持大盘在下,小盘在上,在移动过程中可以利用B座。输出移动盘子的步骤。

这里就拿四个盘来讲述:

我自己画了下详细步骤如下:

 

大家也可以动手画一画,没找到规律前并不是那么好画的!

对于这个问题的算法介绍:

设A柱上最初的盘子
总数为n, 则当n =l时,只要将编号为1的圆盘从塔座A直接移至塔座C上即可;否则,执行以下
三步:
(1) 用 C 柱做过渡,将 A 柱上的(n-l)个盘子移到 B 柱上;
(2) 将 A 柱上最后一个盘子直接移到 C 柱上;
(3) 用 A 柱做过渡,将 B 柱上的(n-l)个盘子移到C柱上。
根据这种解法,如何将 n -1个圆盘从一个塔座移至另一个塔座的问题是一个和原问题具有
相同特征属性的问题,只是问题的规模小1, 因此可以用同样的方法求解。

代码如下:

#include <stdio.h>
int m=0;
void Move(int n,char A,char B,char C)
{
        m++;
        //设置移动盘子的结束条件,如果A当前还有一个盘子那么就把他直接移动到C
        if(n == 1) {
                printf("%c -> %c\n",A,C);
        }else{
        //否则开始递归
                Move(n-1,A,C,B);//递归, 将A上编号为1至n-l的圆盘移到B, C做辅助塔;
                //直接将编号为n的圆盘从A移到C;
                printf("%c -> %c\n",A,C);

                Move(n-1,B,A,C);//递归, 将B上编号为1至n-1的圆盘移到C, A做辅助塔
        }
}

int main()
{
        int n;
        printf("请输入盘子数:");
        scanf("%d",&n);
        //如果有五个盘子,和A,B,C三个柱子,否则开始递归.
        Move(n,'A','B','C');
        printf("移动次数:%d次",m);
}

运行结果这里我输入的盘子数是4

以下是我在网上找到的详细移动步骤对了一下,代码是正确的

 

对于其算法的理解还是必须要深入理解才能写出代码来!!还是有点难的。

 

 

 

  • 63
    点赞
  • 156
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
### 回答1: 汉诺问题可以用递归算法来解决,用C语言实现的话大概是这样: void hanoi(int n, char A, char B, char C) { if(n == 1) { printf("Move disk 1 from %c to %c\n", A, C); return; } hanoi(n-1, A, C, B); printf("Move disk %d from %c to %c\n", n, A, C); hanoi(n-1, B, A, C); } ### 回答2: 汉诺问题是经典的递归问题,通过使用C语言,我们可以编写递归算法来解决这个问题。 首先,我们定义一个函数`hanoi`来解决汉诺问题。该函数接受三个参数:`n`表示要移动的盘子的数量,`start`表示起始柱子,`end`表示目标柱子。 ```c #include <stdio.h> void hanoi(int n, char start, char end) { if (n == 1) { printf("从 %c 移动到 %c\n", start, end); return; } char temp = 'A' + 'B' + 'C' - start - end; // 将n-1个盘子从起始柱子移动到临时柱子 hanoi(n-1, start, temp); // 将最后一个盘子从起始柱子移动到目标柱子 printf("从 %c 移动到 %c\n", start, end); // 将n-1个盘子从临时柱子移动到目标柱子 hanoi(n-1, temp, end); } ``` 在`hanoi`函数中,我们首先判断递归的终止条件,即只有一个盘子时,直接将盘子从起始柱子移动到目标柱子。否则,我们需要将n-1个盘子从起始柱子移动到临时柱子,然后将最后一个盘子从起始柱子移动到目标柱子,最后再将n-1个盘子从临时柱子移动到目标柱子。 使用以上递归算法,我们可以解决汉诺问题。 ### 回答3: 汉诺问题是一个经典的数学问题,通过使用C语言递归算法可以非常简洁地解决。汉诺问题的规则如下:有三根柱子,分别标记为A、B、C,初始时所有的圆盘都放在柱子A上,且按从小到大的顺序从上到下依次叠放。要求通过这三根柱子将所有的圆盘移动到柱子C上,期间可以借助柱子B辅助移动,但必须满足以下规则: 1. 每次只能移动一个圆盘。 2. 大圆盘不能放在小圆盘上面。 使用递归算法来解决汉诺问题可以按照以下步骤: 1. 当只有一个圆盘需要移动时,直接将它从柱子A移动到柱子C上。 2. 当有多个圆盘需要移动时,可以分解为三个步骤: a. 将除了最底下的一个圆盘外的其他圆盘从柱子A移动到柱子B上(借助柱子C)。 b. 将最底下的一个圆盘从柱子A移动到柱子C上。 c. 将之前移动到柱子B上的所有圆盘从柱子B移动到柱子C上(借助柱子A)。 以上步骤可以通过递归的方式重复,直到只有一个圆盘需要移动为止。 下面是用C语言代码实现递归算法解决汉诺问题的示例: ```c #include <stdio.h> void hanoi(int n, char A, char B, char C) { if (n == 1) { printf("Move disk 1 from %c to %c\n", A, C); return; } hanoi(n-1, A, C, B); printf("Move disk %d from %c to %c\n", n, A, C); hanoi(n-1, B, A, C); } int main() { int n = 3; // 圆盘的数量 hanoi(n, 'A', 'B', 'C'); return 0; } ``` 上述代码中,`hanoi`函数接受四个参数,分别表示圆盘的数量`n`,起始柱子`A`,辅助柱子`B`,目标柱子`C`。在递归过程中,会输出每一步的移动操作。最后在`main`函数中调用`hanoi`函数开始解决汉诺问题。 通过递归算法解决汉诺问题可以很好地展示递归思想的威力,相比其他方法更加简洁高效。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Leng_tian

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值