递归函数的应用
调用自身的函数成为递归函数,典型的递归函数的函数体符合如下范例
if(测试终止的条件) renturn (不需要递归的简单解决方案);
else return(包括调用同一函数的递归解决方案)
1.计算 n n n的阶乘 n ! n! n!
递归公式如下:
n
!
=
{
1
(
n
=
0
)
(
n
−
1
)
!
×
n
(
n
>
0
)
n!= \left\{\begin{aligned} &1&(n=0)\\ &(n-1)! \times n&(n>0)\\ \end{aligned} \right.
n!={1(n−1)!×n(n=0)(n>0)
n
=
0
n=0
n=0为终止条件
//求解n的阶乘
//引用方法 p(3)即求3的阶乘
long p(int n)
{
if (n == 0) return 1;
else return n * p(n - 1);
}
2.求解斐波那契数列
定义:斐波那契数列指的是这样一个数列 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233,377,610,987,1597,2584,4181,6765,10946,17711,28657,46368…这个数列从第3项开始,每一项都等于前两项之和。计算公式如下:
F
(
n
)
=
{
1
(
n
=
1
)
1
(
n
=
2
)
F
(
n
−
1
)
+
F
(
n
−
2
)
(
n
>
2
)
F(n) = \left\{ \begin{aligned} &1 \quad &(n=1)\\ &1\quad&(n=2)\\ &F(n-1)+F(n-2) &(n>2)\\ \end{aligned} \right.
F(n)=⎩⎪⎨⎪⎧11F(n−1)+F(n−2)(n=1)(n=2)(n>2)
懒得码字了,放个前不久写的博客的传送门:
斐波那契数列递归算法
3.汉诺塔(Hanoi)问题
这是一个古老的问题。相传印度教的天神梵天在创造地球这一世界是,建了一座神庙。神庙内有三根宝石柱子,柱子有一个铜座支撑。梵天将64个直径大小不一的盘子按照从大到小的次序依次套放在第一根柱子上,形成一座金塔,即所谓汉诺塔。天神让庙里的僧侣们将第一根柱子上的64个盘子借助第三根柱子全部移到第二根柱子上。同时定下三条规则:
- 每次只能移动一个盘子;
- 盘子只能在三根柱子间移动
- 在移动过程中,三根柱子上的盘子必须始终保持大盘在下,小盘在上。
若只有三个盘子,则移动图解如下(由第一根柱子移到第三根):
(注:图片来源于网络)
汉诺塔问题是一个典型的只能用递归解决的问题,直接写出64个盘子的每一个具体步骤是不可能的。但是利用递归我们可以很轻松的解决这个问题。我们可以将64个盘子的汉诺塔问题转化为63个盘子的汉诺塔问题…依次递归下去,直至一个盘子的问题。
//Hanio问题:将n个盘子从start借助temp移动到finish
#include <iostream>
using namespace std;
void Hanoi(int n, char start, char finish, char temp)
{
if (n == 1) cout << start << "->" << finish << endl;
else {
Hanoi(n - 1, start, temp, finish);//把n-1个盘子从start移到temp
cout << start << "->" << finish << endl;//把第一根柱子上的最后一个盘子移到finish
Hanoi(n - 1, temp, finish, start);//把现在在temp的n-1个柱子移到finish
}
}
int main() {
int n;
cout << "共有多少个盘子需要移动" << endl;
cin >> n;
Hanoi(n, 'A', 'B', 'C');
}
输出结果如下:
n
=
3
n=3
n=3时的情况:
n
=
5
n=5
n=5时的情况:
递归实现n个字符的全排列
要显示n个字符的全排列,可以依次把n个字母中的每个字母置于列首,其后跟着剩下n-1个字符的全排列,这样就得到了全排列问题的递归解。
在保证前k个字母保持不变的条件下,让他产生一个字符串的所有排列。当k=0时,所有字母都可以变动;当k值等于字符串长度,就没有字符可以互相变动位置,表示得到了一个全排列。
#include <iostream>
using namespace std;
//交换数组str中的第i和第k个元素
void swap(char str[], int k, int i)
{
int tmp;
tmp = str[k];
str[k] = str[i];
str[i] = tmp;
}
//对于字符串str的第k个字符之后的字符进行全排列
void Permutation(char str[], int k) {
int i;
//当k=字符串的长度时直接输出该字符串
if (k == strlen(str)) cout << str << endl;
else {
for (i = k; i < strlen(str); ++i)
//对从k开始到字符串结束前的每个位置i上的字符
{
swap(str, k, i);//交换i和k的位置
Permutation(str, k + 1);//生成前k+1个字符固定情况下的全排列
swap(str, k, i);//重新交换i和k的字符,回复原先的字符串
}
}
}
//对于一般情况,生成字符串中全部字符的全排列
//包装函数
void ListPermutation(char str[])
{
Permutation(str, 0);
}
int main()
{
const int maxnum = 100;
int n,k;
char flag;
char str[maxnum];
cout << "请输入您要排列的字符总个数:" << endl;
cin >> n;
cout << "请输入字符串" << endl;
cin >> str;
cout << "请问是否要进行全排列 YorN" << endl;
cin >> flag;
if (flag == 'N') {
cout << "从第几个字符开始全排列" << endl;
cin >> k;
cout << "符合条件的所有排列如下:" << endl;
Permutation(str, k);
}
else {
cout << "全排列如下" << endl;
ListPermutation(str);
}
return 0;
}
运行结果如下:
不进行全部字符的全排列:
进行全部字符的全排列:
第一期一些有关递归函数简单的例子就到这里结束,下期有关递归函数的算法再见!