经典的算法

来源:互联网 发布:sql update 多个字段 编辑:程序博客网 时间:2024/05/17 23:17

今天无意中从箱子里发现了大学时学算法的教材《算法设计与分析》,虽然工作这么几年没在什么地方用过算法,但算法的思想还是影响深刻的,可以在系统设计时提供一些思路。大致翻了翻,重温了一下几种几种经典的算法,做一下小结。

  • 分治法
  • 动态规划
  • 贪心算法
  • 回溯法
  • 分支限界法

分治法

1)基本思想

将一个问题分解为多个规模较小的子问题,这些子问题互相独立并与原问题解决方法相同。递归解这些子问题,然后将这各子问题的解合并得到原问题的解。

2)适用问题的特征

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

3)关键

  • 如何将问题分解为规模较小并且解决方法相同的问题
  • 分解的粒度

4)步骤

分解->递归求解->合并

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

google的核心算法MapReduce其实就是分治法的衍生

5)分治法例子:合并排序

规约过程:

动态规划

1)基本思想

将待求解问题分解成若干个子问题,但是经分解得到的子问题往往不是互相独立的,如果能够保存已解决的子问题的答案,而在需要时再找出已求得的答案,就可以避免大量重复计算

2)适用问题的特征

  • 最优子结构
  • 在递归计算中,许多子问题被重复计算多次

3)步骤

  • 找出最优解的性质,并刻划其结构特征。
  • 递归地定义最优值。
  • 以自底向上的方式计算出最优值。
  • 根据计算最优值时得到的信息,构造最优解。

贪心算法

1)基本思想

贪心算法总是作出在当前看来最好的选择。也就是说贪心算法并不从整体最优考虑,它所作出的选择只是在某种意义上的局部最优选择

2)适用问题的特征

  • 贪心选择性质,即所求问题的整体最优解可以通过一系列局部最优的选择,即贪心选择来达到。
  • 最优子结构性质

3)步骤:不断寻找局部最优解

4)例子:找硬币,哈夫曼编码,单源最短路径,最小生成树(Prim和Kruskal)

最小生成树图示:

回溯法

1)基本思想

在问题的解空间树中,按深度优先策略,从根结点出发搜索解空间树。算法搜索至解空间树的任意一点时,先判断该结点是否包含问题的解。如果肯定不包含,则跳过对该结点为根的子树的搜索,逐层向其祖先结点回溯;否则,进入该子树,继续按深度优先策略搜索

2)适用问题的特征:容易构建所解问题的解空间

3)步骤

  • 定义问题的解空间 
  • 确定易于搜索的解空间结构
  • 以深度优先方式搜索解空间,并在搜索过程中用剪枝函数避免无效搜索

4)回溯法例子:N皇后问题

分支限界法

1)基本思想

分支限界法常以广度优先或以最小耗费(最大效益)优先的方式搜索问题的解空间树。 在分支限界法中,每一个活结点只有一次机会成为扩展结点。活结点一旦成为扩展结点,就一次性产生其所有儿子结点。在这些儿子结点中,导致不可行解或导致非最优解的儿子结点被舍弃,其余儿子结点被加入活结点表中。此后,从活结点表中取下一结点成为当前扩展结点,并重复上述结点扩展过程。这个过程一直持续到找到所需的解或活结点表为空时为止。

2)分支限界法例子:单源最短路径问题

问题描述:在下图所给的有向图G中,每一边都有一个非负边权。要求图G的从源顶点s到目标顶点t之间的最短路径。