何时使用递归-定义(n!,Fibonacci数列),数据结构(单链表),问题的求解方法(汉诺塔)

                                何时使用递归

一:定义是递归的

有许多数学公式,数列等的定义是递归的。例如,求n!和Fibonacci数列等。对于这些问题的求解可以将其递归定义直接转化为对应的递归算法。
例如:求n!的递归算法:

int fun(int n)
{
    if(n==1)
        return (1);
    else
    return (fun(n-1)*n);
}

例如: 求Fibonacci数列

int Fib1(int n)   /*求Fibonacci数列的第几项*/
{
    if(n==1||n==2)
        return (1);
    else
        return (Fib1(n-1)+Fib1(n-2));  /*它是一个直接递归又是尾递归*/
}
二:数据结构是递归的

有些数据结构是递归的。例如单链表就是一种递归数据结构,其节点类型声明如下:

typedef struct LNode
{
    ElemType data;  /*存放节点数据*/
    struct LNode *next;  /*指向下一个同类型结点的指针*/
}LinkNode;  /*单链表节点类型*/

其中,结构体LNode的声明用到了它自身,即指针域next是一种自身类型结点的指针,所以它是一种递归数据结构。
对于递归数据结构,采用递归的方法编写算法既方便又有效。例如求一个不带头节点的链表L的所有data域(假设为int型)之和的递归算法如下:

int Sum(LinkNode *L)
{
    if(L==NULL)
        return 0;
    else
        return (L->data+Sum(L->next));
}
三:问题的求解方法是递归的

有些问题的解法是递归的,典型的有Hanoi问题求解。

该问题的描述是:相传在古印度圣庙中,有一种被称为汉诺塔(Hanoi)的游戏。该游戏是在一块铜板装置上,有三根杆(编号A、B、C),在A杆自下而上、由大到小按顺序放置64个金盘(如下图)。游戏的目标:把A杆上的金盘全部移到C杆上,并仍保持原有顺序叠好。操作规则:每次只能移动一个盘子,并且在移动过程中三根杆上都始终保持大盘在下,小盘在上,操作过程中盘子可以置于A、B、C任一杆上。

分析:对于这样一个问题,任何人都不可能直接写出移动盘子的每一步,但我们可以利用下面的方法来解决。设移动盘子数为n,为了将这n个盘子从A杆移动到C杆,可以做以下三步:
(1)以C盘为中介,从A杆将1至n-1号盘移至B杆;
(2)将A杆中剩下的第n号盘移至C杆;
(3)以A杆为中介;从B杆将1至n-1号盘移至C杆。

这样问题解决了,但实际操作中,只有第二步可直接完成,而第一、三步又成为移动的新问题。以上操作的实质是把移动n个盘子的问题转化为移动n-1个盘,那一、三步如何解决?事实上,上述方法设盘子数为n, n可为任意数,该法同样适用于移动n-1个盘。因此,依据上法,可解决n -1个盘子从A杆移到B杆(第一步)或从B杆移到C杆(第三步)问题。现在,问题由移动n个盘子的操作转化为移动n-2个盘子的操作。依据该原理,层层递推,即可将原问题转化为解决移动n -2、n -3… … 3、2,直到移动1个盘的操作,而移动一个盘的操作是可以直接完成的。至此,我们的任务算作是真正完成了。而这种由繁化简,用简单的问题和已知的操作运算来解决复杂问题的方法,就是递归法。在计算机设计语言中,用递归法编写的程序就是递归程序。

汉诺塔问题是用递归方法求解的一个典型问题,在实际教学中,可以在传统教学方式的基础上,利用计算机辅助教学进行算法的模拟演示教学,使学生更容易接受和理解递归算法的思想,不但能提高学生的学习兴趣,而且还能取得较好的教学效果。

先写一个C语言的Hanoi1递归算法:

void Hanoil(int n, char X,char Y,char Z)
{
    if(n==1)  /*只有一个盘片的情况,尾递归*/
        printf("\t将第%d个盘片从%c移动到%c\n",n,X,Z);
    else
    {
        Hanoil(n-1,X,Z,Y);
        printf("\t将第%d个盘片从%c移动到%c\n",n,X,Z);
        Hanoil(n-1,Y,X,Z);
    }
}

完整版C++代码:

#include <iostream>

using namespace std;
int hanoi(int n, char r, char m, char s);
int main()
{
    int n;
    cout << "请输入盘子的数量:" << endl;
    cin >> n;
    hanoi(n,'A','B','C');
    return 0;
}

int hanoi(int n, char l,char m, char r)
{
    if (n == 1)
        cout << l << "->" << r << endl;
    else
    {
        hanoi(n-1,l,r,m);//第一步,先把n-1个盘子转到中间柱子上。
        cout << l << "->" << r << endl;//第二步把剩下的那个盘子直接放在目标柱子上。r盘上已经没有盘子了。
        hanoi(n-1,m,l,r);//把中间柱子上的盘子转到右边的柱子上。
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值