注:【算法学习】转载请注明出处!
【算法学习】系列源码均在Linux上编译运行,g++的版本使用的是:
1、递归概念
直接或者间接调用自身的算法叫做递归算法。用函数自身给出定义的函数称为递归函数。有些数据结构,比如二叉树等,由于自身固有的递归特性,特别适合用递归来描述。
ex1: 阶乘问题
对于上述阶乘问题显然可以使用循环的方式来解决。这里使用递归来实现,初步感受递归的使用方式。
#include <iostream>
using namespace std;
int Factorial(int n)
{
if(0 > n)
{
cout<< "Error!" <<endl;
}
else if(0 == n)
{
return 1;
}
else
{
return ( n * Factorial(n-1));
}
}
int main(int argc, char *argv[])
{
int result = Factorial(5);
cout<< result <<endl;
return 0;
}
运行结果:
ex2.斐波那契数列
Fibonacci数列是比较常见的递归问题,其衍生出来的问题也很多。
#include <iostream>
using namespace std;
int Fibonacci(int n)
{
if(0 > n) return -1;
else if(0 == n) return 1;
else if(1 == n) return 1;
else
{
return (Fibonacci(n-2) + Fibonacci(n - 1) );
}
}
int main(int argc, char *argv[])
{
for(int i = 0; i < 9; ++i)
{
cout<< Fibonacci(i) <<" ";
}
cout<<endl;
return 0;
}
运行结果:
对比使用循环的方式,递归算法结构清晰,可读性强,且容易用数学归纳法证明算法的正确性。但是递归算法无论从耗费的时间还是从占用的空间角度看,递归算法的效率都比较低。所以常常在递归算法消除递归调用。
2、分治策略
分治策略的思想是将一个比较大的问题分解成若干个小的问题来求解,各个小问题求解后的结果综合起来得到原问题的解。
3、排列问题
问题描述:
输入n个元素,对这个n个元素进行全排列,列举出所有的结果。
问题分析:第一个元素不动,对后面n-1个元素进行全排列,这样得到的就是以第一个元素为首的所有排列结果,然后将第二个元素作为首元素,对后面n-1个元素进行全排列,依次下去……
总结上述规律,可以将第一个元素分别和数列中的每一个元素作交换,然后递归求解。
代码实现:
#include <iostream>
using namespace std;
int item = 0;
inline void swap(char &a, char &b)
{
char tmp = a;
a = b;
b = tmp;
}
void Perm(char str[], int m, int n)
{
if(m == n)
{
for(int i = 0; i < n; ++i)
{
cout<< str[i] << " ";
}
item++;
cout<<endl;
}
else
{
for(int i = m; i < n; ++i)
{
swap(str[m],str[i]);
Perm(str, m+1, n);
//cout<< str[i] << " ";
}
}
}
int main(int argc, char *argv[])
{
char str[5] = "abcd";
Perm(str, 0, 4);
cout<<"Perm Times:"<<item<<endl;
return 0;
}
运行结果:
注:【算法学习】系列博客来源于《计算机算法设计与分析》王晓东的理解及相关笔记,转载请注明出处!