作者:wsg
时间:2017年8月17日
1、概念:
·一个过程或一个函数,在其定义或者说明中有直接或间接地调用自身的一种思想方法。
2、递归条件:
·子问题和原始问题是相同的事情;
·不能无限制地调用,必须有个出口(边界条件)。
3、如何设计递归算法:
·确定递归公式;
·确定边界条件。
4、递归一般用来解决:
·数据的递归定义;
·递归算法的实现;
·数据结构形式按递归定义(比如二叉树)。
5、递归算法相对于常用的算法(如for循环),运行效率低。若操作不当,很容易造成栈溢出等错误。所以在设计算法的时候,尽量避免使用递归。除非没有更好的算法,或者只能使用递归的时候才使用。
6、经典实例:汉诺塔问题。(后面例3有代码)
7、注意:
·一定要有一个边界条件;
·不要在递归函数里面申请大块内存(malloc)
递归模板:
递归:
1.确定参数
2.确定参数的函数
3.确定简单情况下的函数
4.确定复杂情况下的函数
==============================
模板:
int f(参数)
{
if (简单情况条件)
return 简单情况下函数
else
return 复杂情况下函数
}
汉诺塔:
参数n:盘子个数
设f(n):n个盘子总共需要移动的步数
简单情况下的函数
f(n) = 1 n = 1;
复杂情况下的函数
f(n) = 2f(n-1)+1; //(n > 1)
===============================
例1:输出1-100
/********
===使用for循环做简单很多===
#include <stdio.h>
int main(void)
{
int i;
for(i=1; i<=100; i++)
{
printf("%d\n", i);
}
return 0;
}
*********/
//使用递归算法
#include <stdio.h>
void func(int n);
int main(void)
{
int a = 100;
func(a);
}
void func(int n)
{
if(n>1) //递归的边界条件
{
func(n-1); //函数调用自身,递归
}
printf("%d\n", n);
}
/***可以这样来理解:
void func(int n)
{
if(n>1)
{
if((n-1)>1) //递归的边界条件
{
func((n-1)-1);
//一层一层进去,再从最里面出来,故打印出来的结果就是1-100
}
printf("%d\n", n);
}
printf("%d\n", n);
}
*****/
#include <stdio.h>
int recursion(int n); //声明
int main(void)
{
int a, sum;
printf("请输入一个整数:\n");
scanf("%d", &a);
sum = recursion(a);
printf("结果为:%d\n", sum);
}
int recursion(int n) //递归函数的定义
{
if(n>1)
{
return n*n+recursion(n-1);
//recursion(n-1)将一层一层递归执行return n*n+recursion(n-1)下去,直到n>1不成立。
}
}
#include <stdio.h>
void func(int n, char from, char buf, char to);
int main(void)
{
int n;
char col[3] = {'A','B','C'};//定义三根柱子
printf("请输入圆盘个数:\n");
scanf("%d", &n); //输入有多少个盘
printf("最简移动方案:\n");
func(n,'A', 'B', 'C');
return 0;
}
//用n个盘,原始盘全在from上,要移动到to上,中间工具用buf作过渡
void func(int n, char from, char buf, char to)
{
if(n == 1)
{
printf("%c--->%c\n", from, to);
}
else
{
func(n-1, from, to, buf); //A--->B柱
printf("%c--->%c\n", from, to);
func(n-1, buf, from, to); //B--->C柱
}
}
例3: