递归和分治策略

来源:互联网 发布:vb项目开发全程实录 编辑:程序博客网 时间:2024/06/03 19:23

递归算法

直接或间接地调用自身的算法称为递归算法。用函数自身给出定义的函数称为递归函数
递归(Recursion)就是子程序(或函数)直接调用自己或通过一系列调用语句间接调用自己,是一种描述问题和解决问题的基本方法。

基本要素

  1. 边界条件(递归出口):确定递归到何时终止;
  2. 递归模式(递归体):大问题是如何分解为小问题的。

典型事例

  • 阶乘函数
int Fac(int n){       if(n==0) return 1;//退出递归    else return n*Fac(n-1);//调用自身函数}
  • [ 汉诺塔 ][1] 问题

消除递归方法

  • 采用一个用户定义的栈来模拟系统的递归调用工作栈。该方法通用性强,但本质上还是递归,只不过人工做了本来由编译器做的事情,优化效果不明显。
  • 用递推来实现递归函数。
  • 通过变换能将一些递归转化为尾递归,从而迭代求出结果。

后两种方法在时空复杂度上均有较大改善,但其适用范围有限。


分治算法

将一个难以直接解决的大问题,分割成一些规模较小的相同问题,以便各个击破,分而治之。其中小问题之间是相互独立且与原问题相同。

适用条件

  1. 该问题的规模缩小到一定的程度就可以容易地解决;
  2. 该问题可以分解为若干个规模较小的相同问题,即该问题具有最优子结构性质利用该问题分解出的子问题的解可以合并为该问题的解;
  3. 该问题所分解出的各个子问题是相互独立的,即子问题之间不包含公共的子问题。

典型案例

divide-and-conquer(P){    if ( | P | <= n0) adhoc(P);//解决小规模的问题    divide P into smaller subinstances P1,P2,...,Pk;//分解问题    for (i=1,i<=k,i++)      yi=divide-and-conquer(Pi);  //递归的解各子问题    return merge(y1,...,yk);  //将各子问题的解合并为原问题的解}

分治和递归像一对孪生兄弟,经常同时应用带算法设计中,并由此产生许多高效的算法。

  • 二分搜索技术
  • 大整数乘法
  • Strassen 矩阵乘法
  • 棋盘覆盖
  • 合并排序和快速排序
  • 线性时间选择
  • 最接近点对问题
  • 循环赛日程表