目录
分治的概念:
递归的概念:
分治策略的特征:
分治法步骤:
例:阶乘!
迭代
递归
关于递归使用栈
斐波拉切数列
迭代
递归
分治的概念:
将一个难以直接解决的大问题(规模大),分割成一些规模较小的相同问题,以便各个击破,分而治之。
由分治法产生的子问题往往是原问题的较小规模模式,这为使用递归技术提供了方便,分治与递归经常同时出现。
递归的概念:
函数直接或间接的调用自己。
间接调用:void funa(){funb();} void funb(funa();)
间接递归难以调试,最好不要写
分治策略的特征:
1.问题的规模缩小到一定的程度就可以容易地解决(小易解)
2.问题可以分解为若干个规模较小的相同问题(可分)
3.使用小规模的解可以合并成该问题原规模的解(和=原)
4.小规模直接是相互独立的(独立)
分治法步骤:
1.分解:将问题划分成一些子问题,子问题的形式与原问题相同,规模更小
2.解决:递归地求解子问题。如果子问题的规模足够小,则停止递归,直接求解
3.合并:将小规模的解组合成原规模问题的解
例:阶乘!
f(n) {
= n*f(n-1) n>1
= 1 n=1
迭代
时间复杂度: O(n)
空间复杂度: O(1)
int fun(int n)
{
int sum = 1;
for (int i = 0; i <= n; i++)
{
sum = sum * i;
}
return sum;
}
递归
时间复杂度: O(n)
空间复杂度: O(n)
int fac(int n)
{
if (n <= 1)return 1;
else return fac(n - 1)*n;
}
关于递归使用栈
循环有死循环,但是没有无限递归!!!
因为函数每一次调用都要在栈上开辟一个空间,如果递归没有出口,栈会被占满直到溢出错误。
栈的大小:
Win 1M
linux 10M
linux中用gcc开发可以设置栈空间大小
linux查看修改线程默认栈空间大小 :ulimit -s
1、通过命令 ulimit -s 查看linux的默认栈空间大小,默认情况下 为10240 即10M
2、通过命令 ulimit -s 设置大小值 临时改变栈空间大小:ulimit -s 102400, 即修改为100M
3、可以在/etc/rc.local 内 加入 ulimit -s 102400 则可以开机就设置栈空间大小
4、在/etc/security/limits.conf 中也可以改变栈空间大小:
#<domain> <type> <item> <value>
* soft stack 102400
重新登录,执行ulimit -s 即可看到改为102400 即100M
递归分为递归调用和回归两个过程,调用将问题规模缩小,回归将小问题合成为原规模。
每一次递归调用都要创建一个栈帧,虽然使用参数的名字相同,但它们处于不同栈帧中,是不同的实体。这是多线程中的一个重要思想互不影响。
斐波拉切数列
数列:1 1 2 3 5 8 13 21 34 55…
第n个: 1 2 3 4 5 6 7 8 9 10…
a b
c
迭代
int fun(int n)
{
assert(n > 0);
int a = 1, b = 1, c = 1;
if (n == 1 || n == 2)
return 1;
for (int i = 3; i <= n; i++)
{
c = a + b;
a = b;
b = c;
}
return 0;
}
递归
int fib(int n)
{
if (n == 1 || n == 2)
return 1;
else
return fib(n - 1) + fib(n - 2);
}
时间复杂度:O(2^n) //画图后每一个“结点”增加一块时间
空间复杂度: O(n) //相当于“二叉树”的高度(每一个栈帧利用完就释放)