递归
递归是指,在一个函数或数据结构的定义中直接(或间接)地出现定义本身,这是一个不断深入、细化的过程。
递归的思想比较巧妙,需要自己多去思考,或者多体会别人的代码。
1)函数定义
例如:
阶乘函数,n! = n * (n-1) * ... * 1
int Fact(int n)
{
if(n == 0) return 1; /*若n等于0,阶乘等于1*/
else return n * Fact(n-1); /*否则把n-1传入Fact函数,并与n相乘*/
}
斐波拉契数列,第三个数等于前两个数之和
int Fibonacci(int n)
{
if(n == 1||n ==2) return 1; /*前两个数为1*/
else return Fib(n-1) + Fib(n-2); /*n与n的前两个数由同样的方式计算得到*/
}
2)数据结构定义
例如:
链表结点
typedef struct LNode
{
Elemtype data;
struct LNode *next; /*在结点内部定义指向下一个结点的指针*/
} LNode, *LinkList;
利用链表结点的结构遍历表中的每个结点
/*-------改变指针指向--------*/
void Traverse1(LinkList L)
{
while(L != NULL) /*无递归,要循环*/
{
cout<<L->data;
L = L->next;
}
}
/*-------结合函数的递归定义-------*/
void Traverse2(LinkList L)
{
if(L == NULL) cout<<"Error"; /*无循环,要递归*/
else
{
cout<<L->data;
Traverse2(L->next);
}
}
通过观察上面的代码可以发现,递归可以实现循环的功能。
)问题的递归解法
当处理一个问题时,需要的条件是解决与问题本质相同的问题,那么就可以用到递归算法。
例如:
Hanoi塔问题
现有三个柱子,分别为A、B、C,A柱上从上往下放有由小到大排列的n个圆盘,问题是如何将A柱上的圆盘全部转移到C柱上,且保持圆盘原本的顺序。每次只能移动一个圆盘,且大圆盘必须在小圆盘下面。
【大思路】
1. 以C为辅助柱,先将A的前n-1个圆盘移动到B,然后将第n个圆盘移动到C;
2. 以A为辅助柱,将B的n-1个圆盘移动到C;
3. 第2步包含与第1步相同的操作,只是A与B的“身份”互换,故递归函数中包含前两步的内容。
#include <iostream>
using namespace std;
void move(char main1, int n, char main2)
{
static int timer = 1;
cout<<"第"<<timer++<<"次移动,"<<main1<<n<<main2<<endl;
}
void Hanoi(int n, char A, char B, char C)
{
if(n == 1)
move(A,n,C);
else
{
Hanoi(n-1,A,C,B);
move(A,n,C);
Hanoi(n-1,B,A,C);
}
}
void main()
{
char t1 = 'A', t2 = 'B', t3 = 'C';
int n;
cout<<"请输入圆盘个数n:";
cin>>n;
Hanoi(n,t1,t2,t3);
}
递归工作栈
在高级语言编制的程序中,调用函数与被调用函数之间的链接及信息交换需要栈的支持。
当有多个函数构成嵌套调用时,按照“先调用后返回”的原则,上述函数之间的信息传递和控制转移必须通过栈来实现,即系统将整个程序运行时所需的数据空间安排在一个栈中。
当前正运行的函数的数据区必须在栈顶。