递归算法以及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

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

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

发布了23 篇原创文章 · 获赞 21 · 访问量 5173

猜你喜欢

转载自blog.csdn.net/LTtiandd/article/details/104199368