C++之递归浅谈(一)

递归,就是在运行的过程中调用自己。
构成递归需具备的条件:
1. 子问题须与原始问题为同样的事,且更为简单;
2. 不能无限制地调用本身,须有个出口,化简为非递归状况处理。
递归关系就是实体自己与自己建立关系。斐波那契数列就是(Fibonacci Sequence), 又称黄金分割数列, 指的是这样一个数列:
1, 1, 2, 3, 5, 8, 13, 21, 34......, 斐波那契数列是典型的递归案例。
递归算法一般用于解决三类问题 :
(1)数据的定义是按递归定义的。
例 : 用递归函数输出斐波那契数列

#include<stdio.h>
int Fibonacci(int n)//函数部分;
{
if(n==1 || n==2)
return 1;
if(n>=3)
return Fibonacci(n-1) + Fibonacci(n-2);
}
void main()
{
int Fibonacci(int n);
int n;
printf("请输入n的值:");
scanf("%d",&n);
for(int i=1; i<=n; i++)
{
printf("%12ld",Fibonacci(i));
if(i%4==0) //用于换行 4个一行;
printf("\n");
}
}


 (2)问题解法按递归算法实现。
 例 : 汉诺塔问题
 如下图所示,从左到右有A、B、C三根柱子,其中A柱子上面有从小叠到大的n个圆盘,现要求将A柱子上的圆盘移到C柱子上去,期间只有一个原则:一次只能移到一个盘子且大盘子不能在小盘子上面,求移动的步骤和移动的次数。
 解:(1)n == 1
 第1次  1号盘  A---->C       sum = 1 次
 (2)  n == 2
 第1次  1号盘  A---->B
 第2次  2号盘  A---->C
 第3次  1号盘  B---->C        sum = 3 次
 (3)n == 3
 第1次  1号盘  A---->C
 第2次  2号盘  A---->B
 第3次  1号盘  C---->B
 第4次  3号盘  A---->C
 第5次  1号盘  B---->A
 第6次  2号盘  B---->C
 第7次  1号盘  A---->C        sum = 7 次
 不难发现规律:1个圆盘的次数 2的1次方减1
 2个圆盘的次数 2的2次方减1
 3个圆盘的次数 2的3次方减1
 。  。   。    。   。
 n个圆盘的次数 2的n次方减1
 故:移动次数为:2^n - 1
void m(int n,char x,char y,char z){
    if (n==1) {           //如果只有一个需要移动,直接输出
        printf("%c-->%c\n",x,z);
    }
    else{               //如果有n>1个需要从x移动z,将x最上面的n-1个移动到y,将最后一个移动到z,最后利用递归。将y上面的n-1个移动到z。
        m(n-1,x, z, y);
        printf("%c-->%c\n",x,z);
        m(n-1, y,x,z);
    }
}
int main(){
    int n=0;
    printf("请输入汉诺塔的层数:");
    scanf("%d",&n);
    m(n, 'A', 'B', 'C');
}
(3)数据的结构形式按递归定义
例:树递归遍历
// 递归树.cpp: 定义控制台应用程序的入口点。  
//  
#include "stdio.h"  
#include "stdlib.h"  
//用递归的方式遍历二叉树  
typedef struct node                    //定义二叉树的结点  
{  
    int data;                            //结点的数据  
    struct node*lChild, *rChild;            //结点左右子  
}Node;  
int i = -1;                                //控制下面函数中循环的  
Node *buildTree(int *b)                  //产生二叉树(利用先序递归产生)  
{  
    Node *p;                                //创建一个根结点指针  
    if (b[++i] == 0)p = NULL;                    //如果传入的当前值为0 则设其为空结点  
    else  
    {  
        p = (Node*)malloc(sizeof(Node));      //开辟内存  
        p->data = b[i];                        //设置当前结点的数据  
        p->lChild = buildTree(b);                //左子结点  
        p->rChild = buildTree(b);                //右子  
    }  
    return p;                                //把创建的树的根节点返回  
}  
void preOrder(Node *root)                    //前序遍历  
{  
    if (root != 0)                            //如果根节点不为0  
    {  
        printf("%d ", root->data);                //打印当前结点  
        preOrder(root->lChild);                //指向左子  
        preOrder(root->rChild);                //指向右子  
    }  
}  
void inOrder(Node *root)                    //中序遍历  
{  
    if (root != 0)                            //如果根节点不为0  
    {  
        inOrder(root->lChild);                //指向左子  
        printf("%d ", root->data);                //打印当前结点  
        inOrder(root->rChild);                //指向右子  
    }  
}  
void postOrder(Node *root)  
{  
    if (root != 0)  
    {  
        postOrder(root->lChild);                //指向左子  
        postOrder(root->rChild);            //指向右子  
        printf("%d ", root->data);                //打印当前结点  
    }  
}  
void main()  
{  
    //按先序次序输入树的结点(非0整数)来创建一个树 空结点用0表示  
    int a[] = { 1,2,4,0,7,0,0,0,3,5,0,0,6,8,0,0,9,0,0 };  
    int *b = a;  
    //将指向数组首地址的指针传给  bulidTree 函数 来创建树  
    Node *root = buildTree(b);  
    printf("用递归方法 \n\n前序遍历:  ");        //打印提示内容  
    preOrder(root);                                            //调用前序遍历函数  
    printf("\n中序遍历:  ");                            //打印提示内容  
    inOrder(root);                                                //调用中序遍历函数  
    printf("\n后序遍历:  ");                            //打印提示内容  
    postOrder(root);                                            //调用后序遍历函数  
  
}  


猜你喜欢

转载自blog.csdn.net/ox0080/article/details/79958781