递归:程序直接或间接调用自身的编程技巧称为递归算法(Recursion)。
😉 递归是处理办法,分治是手段。
一个过程或函数在其定义或说明中又直接或间接调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解。递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。
递归的优势在于用有限的语句来定义对象的无限集合。
递归的缺点:
递归算法解题的运行效率较低。
在递归调用过程中,系统为每一层的返回点、局部变量等开辟了堆栈来存储。递归次数过多容易造成堆栈溢出等。
递归思路:
1.递归需要有边界条件、递归前进段和递归返回段。
2.当边界条件不满足时,递归前进;
3.当边界条件满足时,递归返回。
注意:在使用递增归策略时,必须有一个明确的递归结束条件,称为递归出口,否则将无限进行下去(死锁)。
递归算法一般用于解决3类问题:
1、数据的定义是按递归定义的。如Fibonacci函数。
2、问题解法用递归算法实现。如回溯算法。
3、数据的结构形式是按递归定义的。如树的遍历,图的搜索。
递归的优势在于用有限的语句来定义对象的无限集合。
算法1 Fibonacci数列的递归算法
int fib(int n)
{
if (n<=1) return 1;
return fib(n-1)+fib(n-2);
}
该算法的效率非常低,因为重复递归的次数太多。
算法2 Fibonacci数列的递推算法
int fib[50];//采用数组保存中间结果
void fibonacci(int n)
{
fib[0] = 1;
fib[1] = 1;
for (int i=2; i<=n; i++)
fib[i] = fib[i-1]+fib[i-2];
}
分治策略是对于一个规模为n的问题,若该问题可以容易地解决(比如说规模n较小)则直接解决,否则将其分解为k个规模较小的子问题,这些子问题互相独立且与原问题形式相同。递归地解这些子问题,然后将各子问题的解合并得到原问题的解。
分治法在每一层递归上都有3个步骤:
(1)分解:将原问题分解为若干个规模较小,相互独立,与原问题形式相同的子问题;
(2)解决:若子问题规模较小而容易被解决则直接解,否则递归地解各个子问题;
(3)合并:将各个子问题的解合并为原问题的解。
分治法所能解决的问题一般具有以下几个特征:
(1)该问题的规模缩小到一定的程度就可以容易地解决;
(2)该问题可以分解为若干个规模较小的相同问题,即该问题具有最优子结构性质;
(3)利用该问题分解出的子问题的解可以合并为该问题的解;
(4)该问题所分解出的各个子问题是相互独立的,即子问题之间不包含公共的子子问题。
二分搜索算法的基本思想是将n个元素分成个数大致相同的两半,取a[n/2]与x作比较。
如果x=a[n/2],则找到x,算法终止。
如果x<a[n/2],则我们只要在数组a的左半部分继续搜索x。
如果x>a[n/2],则我们只要在数组a的右半部分继续搜索x。
int BinarySearch(int a[],const int& x,int n)
{
int left=0;//左边界
int right=n-1;//右边界
while(left<=right)
{
int middle=(left+right)/2;//中点
if (x==a[middle]) return middle;
if (x>a[middle]) left=middle+1;
else right=middle-1;
} return -1;//未找到x
}