算法导论读书笔记(16)贪心算法

第四部分 高级设计和分析技术

第16章 贪心算法

贪心算法在每一步都做出当时看起来最佳的选择,它总是做出局部最优的选择,寄希望这样的选择能导致全局最优解。

1. 活动选择问题

有一个需要使用每个资源的n个活动组成的集合S= {a1,a2,···,an },资源每次只能由一个活动使用。每个活动ai都有一个开始时间si和结束时间fi,且 0≤ si < fi <∞ 。一旦被选择后,活动ai就占据半开时间区间[si,fi)。如果[si,fi]和[sj,fj]互不重叠,则称ai和aj两个活动是兼容的。该问题就是要找出一个由互相兼容的活动组成的最大子集。例如下图所示的活动集合S,其中各项活动按照结束时间单调递增排序。
这里写图片描述
从图中可以看出S中共有11个活动,最大的相互兼容的活动子集为:{a1,a4,a8,a11,}和{a2,a4,a9,a11}。

递归贪心算法

贪心算法通常采用自顶向下的设计,因为不需要做出过多的选择而求解所有的子问题。
Recursive-Activity-Selector(s, f, k, n)
m = k + 1

// find the first activity in Sk to finish
while m <= n and s[m] < f[k]
    m = m + 1

if m <= n
    return {am} U Recursive-Activity-Selector(s, f, m, n)
else
    return Ø
### 迭代贪心算法
Greedy-Activity-Selector(s, f)
    n = s.length
    A = {a1}
    k = 1
    for m = 2 to n
        if s[m] >= f[k]
            A = A U {am}
            k = m
    return A

2. 贪心算法原理

贪心选择性质

第一个关键要素是该性质:我们可以通过做出局部最优(贪心)选择来构造全局最优解。换句话说,当进行选择时,我们直接做出在当前问题中看来最优的选择,而不必考虑子问题的解。
动态规划方法中,每个步骤都要进行一次选择,但选择通过依赖于子问题的解。因此,我们通常以一种自底向上的方式来解动态规划问题,先求解较小的子问题,然后是较大的子问题
贪心算法中,总是做出当时看来最佳的选择,然后求解剩下的唯一的子问题。

最优子结构

如果一个问题的最优解包含其子问题的最优解,是称此问题具有最优子结构性质。当应用于贪心算法时,我们通常使用更为直接的最优子结构。我们可以假定,通过对原问题应用贪心选择即可得到子问题。我们真正要做的全部工作就是论证:将子问题的最优解与贪心选择组合在一起就能生成原问题的最优解。

3. 赫夫曼编码

讨论赫夫曼编码问题,赫夫曼编码的思想就是变长编码变长编码就是让字符表中出现概率高的字符的编码长度尽可能小,而出现概率高的字符的编码长度相对较长。然后还要遵循前缀码的要求,就是任意一个编码都不是其他编码的前缀码,这样方便解码。

构造赫夫曼编码

Huffman(C)
    n = |C|
    Q = C
    for i = 1 to n
        allocate a new node z
        z.left = x = Extract-Min(Q)
        z.right = y = Extract-Min(Q)
        z.freq = x.freq + y.freq
        Insert(Q, z)
    return Extract-Min(Q)   // return the root of the tree
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值