关闭

研究生课程 算法分析-分治法

标签: 算法分治法递归快速排序归并排序
244人阅读 评论(0) 收藏 举报
分类:

分治法(divide and conquer)是算法分析里比较直观和朴素的思想,应用也很广泛。

分治法的思想

分治法的思想是,把一个复杂的问题 P 划分称 k 个子问题,这些子问题相互独立且与原问题相同。递归调用子问题,直到问题规模足够小,可以很容易地求解为止;接着,把小规模的问题的解合并成一个更大规模的问题的解。

可以用下面的伪代码来描述,

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, y2,...,yk);      // 合并为原问题的解
}

分治法和递归

从分治法的思想可以看出,在求解子问题的时候往往需要用到递归,因此分治法和递归经常一起出现。递归算法的优点是结构清晰,可读性强,一般代码也比较容易写,但是缺点是运行效率很低,无论是计算时间还是占用的存储空间都很大。

一般有下面几种解决的办法,

  1. 用自定义栈,做了编译器做的事,优化效果不明显。
  2. 用递推的方法来实现递归函数
  3. 通过变换,将一些递归转化成尾递归(尾递归是所有子递归出现在递归函数的尾部),迭代求结果

后两种方法虽然范围有限,但是如果可以在问题中这样优化的话,效果会比较好。

分治法的适用条件

看一个问题是否可以用分治法求解,可以考虑这个问题是否符合下面几种条件,

  1. 小规模时,问题容易求解,这个一般都很容易满足。
  2. 问题具有 最优子结构 的性质,即可以分解成若干个规模较小的相同问题。
  3. 子问题的解可以 合并为该问题的解
  4. 子问题相互独立,即 不包含公共的子问题

满足前三条特征,可以用分治法;如果不具备第三条特征,可以考虑贪心算法和动态规划。如果问题满足第 4 个特征的话,分治法会重复计算导致效率,用动态规划较好。

分治法的应用

二分查找算法

二分查找要解决的问题是,从有序数组 a 中找出特定元素 x 出来。因为是有序,所以可以用考虑分治法,从线性扫描的复杂度 O(n) 优化到 O(logn)

有递归和非递归两种实现方法。

大整数的乘法

大整数的乘法,分治成较小规模的子问题后,从四次乘法的优化到三次乘法,可以把复杂度从 O(n2) 优化到 O(nlog3=1.59),有较大的改进。

Strassen 矩阵乘法

与大数乘法的例子类似,做分治后想办法减少乘法的次数,从 O(n3) 优化到了 O(nlog7=2.81) 的复杂度。

归并排序

基本思想是,把待排序的数组分成两个子集,分别排序后再合并。递归代码如下,

void merge_sort(int a[], int start, int end) {
    if (start < end) {
        int mid = (start + end) / 2;
        merge_sort(a, start, mid);     // 对左边的序列递归排序
        merge_sort(a, mid + 1, end);   // 对右边的序列递归排序
        merge(a, start, end);          // 合并子序列
    }
}

快速排序

快排的想法很简单,是想找一个数作为排序的基准(pivot),小的放左边,大的放右边。然后对左边和右边的两个子问题递归排序。递归实现如下,

void quick_sort(int a[], int start, int end) {
    if (start < end) {  // 
        int pivot_index = partition(a, start, end);  // 挖坑划分
        quick_sort(a, start, pivot_index - 1);       // 左边的子序列递归排序
        quick_sort(a, pivot_index + 1, end);         // 右边的子序列递归排序
    }
}

注意快排的划分函数 partition,用的是挖坑填坑的方法。以第一个元素为基准(pivot),最后返回 pivot 的位置 pivot_index。此时左边的数组元素都比 pivot 小,右边的数组元素都比 pivot 大。

0
0
查看评论
发表评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场

分享:中国科学院开放视频课程/研究生课程全套系列

《中国科学院时间序列分析》研究深课程【2.5GB】  http://www.xuexi111.com/jiaocheng/shipin/29168.html  《美国近现代科技史》中科院研究生课程...
  • zheng_ren_feng
  • zheng_ren_feng
  • 2013-03-12 09:37
  • 2152

数学系研究生不错的一份参考书目

网上整理:   全文转载自繁星客栈望月殿:在网上找书的时候恰好看到这个,看着觉得的确是经典书目大全,贴在这里供学弟学妹们参考:)其中所谓第几学年云云,各校要求不同,像我所在的学校,一般学生第一年选...
  • mao_kun
  • mao_kun
  • 2014-02-26 13:41
  • 9122

陶行知:学生自治问题之研究

偶尔看到陶行知先生在五四时期写的一篇文章,谈学生自治。想着当下校园中的一些事情,还是可以给我们很多启示的。其中的期望,不仅是校方能够给学生多少自主,更在乎学生在现有框架下是否抓住了可以把握的自主,让旁...
  • sxhelijian
  • sxhelijian
  • 2013-11-21 09:06
  • 4807

研究生课程 算法分析-回溯法和分支限界法

回溯法(backtrack)有许多问题,当需要找出它的解集或者要求回答什么解是满足某些约束条件的最佳解时,往往要使用回溯法。回溯法的基本做法是 搜索,或是一种组织得井井有条的,能避免不必要搜索的穷举式...
  • zhangxb35
  • zhangxb35
  • 2016-12-31 13:26
  • 657

研究生课程 算法分析-贪心法

贪心法的思想在求解一些最优化问题的时候,一般会分成多个步骤,每一步都有一个选择。贪心算法的思想在于,先不从整体考虑,每次都只做当前看来最优的思想,即局部最优解,期望通过一步步的局部最优解,最后构造出全...
  • zhangxb35
  • zhangxb35
  • 2016-12-31 12:45
  • 380

算法设计与分析 汉诺塔 分治法

  • 2013-04-13 11:18
  • 17KB
  • 下载

算法分析之分治法

  • 2014-07-08 19:05
  • 102KB
  • 下载

算法设计和分析-分治法

  • 2015-10-22 22:08
  • 812KB
  • 下载

算法设计与分析之分治法

  • 2015-06-18 20:57
  • 55KB
  • 下载

算法设计与分析中的分治法

  • 2014-06-16 22:56
  • 109KB
  • 下载
    个人资料
    • 访问:163487次
    • 积分:1907
    • 等级:
    • 排名:千里之外
    • 原创:85篇
    • 转载:1篇
    • 译文:0篇
    • 评论:31条
    联系方式
    中山大学数据科学与计算机学院 张小彬

    关注机器学习,深度学习,NLP

    很少看私信,请邮箱联系 zhangxb.sysu@gmail.com

    文章分类
    最新评论