递归——求n! 和 Hanoi汉诺塔问题

什么是递归?

在定义一个过程或函数时出现调用本过程或本函数的成分,称为递归。若调用自身,称为直接递归。若过程或函数p调用过程或函数q,而q又调用p,称为间接递归。

 

尾递归:如果一个递归过程或递归函数中递归调用语句是最后一条执行语句,则称这种递归调用为尾递归。

 

递归算法通常把一个大的复杂问题层层转化为一个或多个与原问题相似的规模较小的问题来求解,只需要少量的代码就可以描述出解题过程所需要的多次重复计算,大大减少了算法的代码量。

所有的递归函数都能找到对应的非递归定义

 

一般来说,能够用递归解决的问题应该满足一下三个条件:

  1. 需要解决的问题可以转化为一个或多个子问题来求解,而这些子问题的求解方法与原问题完全相同,只是在数量规模上会有所不同
  2. 递归调用的次数必须是有限的
  3. 必须有结束递归的条件来终止递归

 

递归算法求解过程是:先将整个问题划分为若干个子问题,通过分别求解子问题,最后获得整个问题的解。这种自上而下将问题分解、求解,再自下而上引用,合并,求出最后解答的过程成为递归求解过程。这是一种分而治之的算法设计方法。递归调用是函数嵌套调用的一种特殊情况,即它是调用自身代码。

1、每递归调用一次,就需要进栈一次,进栈次数成为递归深度,当n越大,递归深度越深,开辟的栈空间也越大

2、每当遇到递归出口或完成本次执行时,需从栈顶元素中得到返回地址,并恢复参量值,当全部执行完毕时,栈应为空

 

递归的实现需要用到栈,关于栈的概念,这里只做简单介绍,若要了解详细的知识,可以翻翻《数据结构》之内的书,上面都有做详细介绍

通常在使用二叉树算法,或者将递归算法转换成非递归算法时需要使用栈。是一种只能在一段进行插入或删除操作的线性表。表中允许进行插入、删除操作的一端称为栈顶,栈顶的当前位置是动态的,由一个称为栈顶指针的位置指示器指示。表的另一端成为栈底,栈中没有数据元素时,成为空栈。栈的插入操作通常称为压栈进栈,栈的删除操作通常称为退栈出栈。栈的特点是先进后出

 

何时使用递归?

1、定义是递归的

     有许多数学公式、数列等的定义是递归的。例如n!和斐波拉契数列。

2、数据结构是递归的

     有些数据结构是递归的,如单链表,其结点类型如下:

            typedef struct LNode{

                 ElemType  data;

                 struct  LNode *next;

            }LinkList;

      该定义中,结构体LNode的定义中用到了它自身,即指针域next是一种指向自身类型的指针,所以它是一种递归数据结构。

3、问题的求解方法是递归的

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

 

求n!的递归实现

#include<stdio.h>
#include<iostream>
using namespace std;
//求n!
int factorial(int n){
	if(n==1)
		return 1;
	else
		return n*factorial(n-1);//递归
}
int main(){
  int n;
  cout<<"n:";
  cin>>n;
  cout<<n<<"!"<<"="<<factorial(n)<<endl;
}

《递归——求n! 和 Hanoi汉诺塔问题》

 

用递归算法实现汉诺塔问题

典型的Hanoi问题:

           设有3个分别命名为A,B和C的塔座,在塔座X上有n个直径各不相同,从小到大依次编号1,2,3……n的盘片,现要求将A塔座上的n个盘片移到塔座C上并仍按同样的顺序叠放,盘片移动时必须遵守以下规则:每次只能移动一个盘片,盘片可以插在A、B和C中任一塔座,任何时候都不能将一个较大的盘片放在较小的盘片上。

《递归——求n! 和 Hanoi汉诺塔问题》

#include<stdio.h>
#include<iostream>
using namespace std;
void move(int n,char a,char b,char c)
{
    if(n==1)
       cout<<a<<"->"<<c<<endl;    //当n只有1个的时候直接从a移动到c
    else
    {
        move(n-1,a,c,b);            //第n-1个要从a通过c移动到b
      cout<<a<<"->"<<c<<endl;
        move(n-1,b,a,c);            //n-1个移动过来之后b变开始盘,b通过a移动到c,这边很难理解
    }
} 
int main()
{
    int n;
    cout<<"请输入要移动的块数:";
    cin>>n;
    move(n,'a','b','c');
              return 0;
}

 

《递归——求n! 和 Hanoi汉诺塔问题》

 

    原文作者: 汉诺塔问题
    原文地址: https://blog.csdn.net/zmeilin/article/details/81143425
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞