6算法设计与分析笔记(Authored by M.H Alsuwaiyel, Saudi)

第六章 贪心算法

  • 顾名思义,贪心算法总是作出当前看来最好的选择,也就是说贪心算法并不从整体最优考虑,是某种意义上的局部最优解。许多情况下,局部最优的组合就是整体最优解。

小数背包问题GREEDYKNAPSACK

  • 相较于0/1背包问题,小数背包是指在选择把物品i装入背包时,可以选择物品的一部分(价值与体积成正比),而不是全部装入背包。

  • 由于是按比率放入背包,我们可以贪心地先放性价比最高的,再放其次的······直到背包被装满,这样得到的背包价值一定最大。

GREEDYKNAPSACK

输入:物品集合U={u1, u2,..., un},体积分别为s1, s2,..., sn,价值分别为v1, v2,..., vn,容量为C的背包。

输出:\sum_{u_i\in S}v_i在约束条件\sum_{u_i\in S}s_i \leq C下最大,S\subseteq U

comment: 物品已经按性价比降序排列好
x <- 0 #x(i)指示着第i个物品被选择多少,1表示全部选择
c <- C
for i <- 1 to n
    if w(i) <= c then
        x(i) <- 1
        c <- c - w(i)
    else exit
if i <= n
    then x(i) <- c/w(i)
return x

霍夫曼编码Huffman Coding

  • 计算机数据处理中,霍夫曼编码使用变长编码表对源符号(如文件中的一个字母)进行编码,其中变长编码表是通过一种评估来源符号出现机率的方法得到的,出现机率高的字母使用较短的编码,反之出现机率低的则使用较长的编码,这便使编码之后的字符串的平均长度、期望值降低,从而达到无损压缩数据的目的。

  • 霍夫曼编码的具体操作

    • 将信号源符号按照出现概率从大到小排序(此时为n棵树的森林,特殊地是每棵树只有一个节点);
    • 将最小的两个符号概率p_1,p_2相加得到新概率p_3,并由新概率p_4为根,p_1,p_2中的较大者为右孩子,较小者为左孩子将合并的新树加入森林,递归上述操作,直到将所有节点构成一棵树;
    • 易知,最终的根节点概率为1,依照“左01”的规则对节点间的路径编号;
    • 对于树上的每个字符节点,其霍夫曼编码就是根节点到该节点的唯一路径编号组合

    例如,经统计信号源符号满足:P(a)=0.45,P(b)=0.13,P(c)=0.12,P(d)=0.16,P(e)=0.09,P(f)=0.05,请构造霍夫曼树并求每个字符的编码。

    • 每次合并后,将由新的根节点取代原来的树。例如第二步,f、e合并为14后,接下来是取12、13、14、16、45的最小两个12、13

    最终得到

    字符 编码
    a 0
    b 101
    c 100
    d 111
    e 1100
    f 1101

HUFFMAN

输入:n个字符的集合C={c1, c2,..., cn}和它们的频度{f(c1), f(c2),..., f(cn)}。

输出:C的Huffman树(V, T)。

根据频度将所有字符插入最小堆H
V <- C; T = {}
for j <- 1 to n-1
    c1 <- DELETEMIN(H)
    c2 <- DELETEMIN(H)
    f(v) <- f(c1) + f(c2) #新节点v的频度
    INSERT(H, v) #将v替代c1,c2加入最小堆
    V = V并{v}
    T = T并{(v, c1), (v,c2)}
end while

生成树Minimum Spanning Tree,MST

  • 定义:设G=(V,E)是无向连通带权图(也称为一个网络)。E中每条边(v,w)的权值为c[v][w]如果G的子图G’是一棵包含G的所有顶点的树,则称G’G的生成树。生成树上各边权的总和称为该生成树的耗费。在G的所有生成树中,耗费最小的生成树称为G的最小生成树

Prim算法

  • Prim算法从建立两个集合开始:X=\{1\},Y=\{2,3,...,n\}。在每一步中,选取X集合到Y集合的权重最小的边(x,y),x\in X,y\in Y(这条边当然不会与X集合的顶点形成环,否则找次小边),并将y加入X,直到集合Y为空。

  • 例如如下,从顶点S开始:

    • 7,8中选择7,将A加入集合X

    • 8,3,6中选择3,将C加入集合X

    • 6,4,3中选择3,将D加入集合X

      ······

PRIM

输入:含权连通无向图G(V,E),V={1, 2,..., n}。

输出:由G生成的最小耗费生成树T组成的边的集合。

comment: 图G用二维数组A表示。
T <- {}; X <- {1}; Y <- V-{1} #T的元素为(x,y)指示一条边
while Y not empty:
    min = infty
    #两层for循环找出X->Y的最短边
    for each i in X:
        for each j in Y:
            if A[i][j] < min then 
                min <- A[i][j]
                x <- i
                y <- j
            end if
        end for
    end for
    X <- X并{y}
    Y <- Y减{y}
    T <- T并{(x,y)}
end while
return T
  • 易知,while循环执行n次,第k次迭代查找最小边花费k(n-k)的时间,T(n)=\sum_{k=1}^{n}{k*(n-k)}=\Theta(n^2)

Kruskal算法

  • Prim算法可以从任意一个顶点开始执行可能产生多种最小生成树,与Prim算法十分类似,Kruskal算法也是将顶点分为两个集合,按照一定规则进行搬运。

  • 思路:

    • 将图G=(V,E)按照边的权值大小从小到大排序;
    • 每次从边集合V中取出一条边,若不与生成树集合T内的点连通则加入T中,否则将其舍弃寻找下一条边。
  • 例子如下:

    • (h,g)=1,加入T

    • (i,c)=2,加入T

      ······

    • (i,g)=6,加入会使得cigf连通,舍弃;

    • (c,d)=7,不与T构成连通,加入T

      ······

KRUSKAL

输入:包含n个顶点的含权连通无向图G=(V,E)。

输出:由G生成的最小耗费生成树T组成的边的集合。

按非降序权重将E中的边重新排序
for each v in V
    MAKESET({v})
end for
T = {}
while |T| < n - 1
    令(x, y)为E中的下一条边
    if FIND(x) != FIND(y) then 
        将(x, y)加入T
        UNION(x, y)
    end if
end while
return T

单源最短路径

  • G=(V,E)是一个每条边有非负长度的有向图,给定一个特殊顶点s,称为源。需要确定源sV中其他顶点的距离,这里顶点s到顶点x的距离定义为从sx的最短路径距离。
  • 下面介绍解决该问题的一个算法:Dijkstra算法。该算法与Floyd算法的执行过程十分类似,不断试探中间顶点对最短路径的影响。

Dijkstra算法

  • 初始时,将顶点分为两个集合X=\{1\},Y=\{2,3,...,n\}X包含的顶点有这样的特征:从源s到这些顶点距离已经确定。定义\lambda[y]为从源到y(仅经过X内的顶点)的最短路径值。
  • 在每一次迭代中,我们选择y\in Y~and~\lambda[y]最小,将该顶点加入X中,同时将顶点y作为中间点更新X中的所有最短路径(如果需要的话)。

DIJKSTRA

输入:含权有向图G=(V,E),V={1, 2,..., n}。

输出:G中顶点1到其他顶点的距离。

X = {1}; Y <- V - {1}; l[1] <- 0
for y <- 2 to n
    if y相邻于1 then l[y] <- length[1,y]
    else l[y] <- infty
    end if
end for
for j <- 1 to n-1
    取y属于Y,且l[y]最小
    X <- X并{y}
    Y <- Y减{y}
    for each w in X
        if l[y] + length[y,w] < l[w] then
            l[w] <- l[y] + length[y,w]
    end for
end for

Bellmen-Floyd算法

  • 松弛操作relax(v_i,v_j):假设已知一条从v_0\rightarrow v_j的路径长度为d,而通过节点v_i的路径v_0\rightarrow v_i \rightarrow v_j的路径更短,则更新v_0\rightarrow v_j的路径为较短值,这个操作称为松弛。

  • 过程:

    • 初始时,设置源点d值为0,其余节点设为0(最终节点的d值指示着和源点的距离);
    • 遍历每一条边,并尝试将该边加入路径,进行松弛操作。
    • 最后遍历一次边,若节点d值改变,说明不存在最短路径(即存在负权值边);

BELLMAN-FLOYD

输入:含权有向图G=(V,E),V={1, 2,..., n}。

输出:G中顶点1到其他顶点的距离。

d[1] <- 0
for each v in V-{1}
    d[v] <- infty
for i <- 1 to |V|-1
    for each edge(u,v) in E #使用邻接表更容易实现该算法
        if d[v] > d[u] + w(u,v) then
            d[v] <- d[u] + w(u,v)
        end if
    end for
end for
for each edge(u,v) in E
    if d[v] > d[u] + w(u,v)
        then report a negative-weight cycle exists.
return d
  • 时间复杂度为O(VE)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,122评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,070评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,491评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,636评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,676评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,541评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,292评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,211评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,655评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,846评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,965评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,684评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,295评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,894评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,012评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,126评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,914评论 2 355

推荐阅读更多精彩内容