算法复习—贪心

本文介绍了贪心算法的基本概念,探讨了其在求解最优化问题中的应用,如背包问题中的价值体积比选择,以及Dijkstra、Kruskal和Prim算法在最短路径和最小耗费生成树中的解决方案。同时提及了Huffman树在文件压缩中的角色,强调了算法的效率和前缀约束的重要性。
摘要由CSDN通过智能技术生成

贪心算法

引言

和动态规划算法的相似,通常用来求解最优化问题,即量的最大化或最小化。

通常包含一个用于寻找局部最优解的迭代过程。它的每一步均是建立在局部最优解的基础上,而又扩大了部分解的规模,做出的选择产生最大的直接受益而又保持可行性

  • 背包问题

    可以采用贪心策略方便的解出:对于每项计算vi / si ,即该项的价值与体积之比,再按照比值的降序排列,从第一项开始装包,直至装不下。

    在维持可行性的前提下,它选择能产生最大直接利益的项。

最短路径

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

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

设G=(V,E)是一个每条边有非负长度的有向图,有一个特异顶点S为源点

单源最短路径(简称为最短路径问题 )就是要确定S到V中每一个其他顶点的距离

初识时将顶点分为两个集合X={ 1 },Y={ 2,3,…,n },X中的顶点是源点到这些顶点的距离已经确定的。在每一步中,我们选择Y中已经获得与源点距离的顶点y,并加入X中。然后更新与y相邻的每个顶点w的标记,表示找到了经过y到w的更短路径。

ℒ[y]表示只经过X中顶点的最短路径的长度

算法DIJKSTRA1

X = {1}; Y=V-{1};[1]=0
for y: 2 to n
  if y邻接于1  then ℒ[y]=length[1,y]
  else[y]=∞
  end if
end for
for j: 1 to n-1
  令y∈ Y,使得ℒ[y]为最小
  X= X U {y}
  Y= Y - {y}
  for 每条边(y,w)
    if w∈ Y and ℒ[y]+length[y,w] <[w]  then
      ℒ[w]=[y]+length[y,w]
  end for
end for

假设输入由邻接表表示,边(x,y)的长度存放在x的邻接表的y顶点中,把两个集合X和Y用布尔向量X[1…n]和Y [1…n]来表示:初始时X[1]=1,Y[1]=0,并且对于所有的其他顶点都设置为X[i]=0,Y[i]=1。该点进入X通过置X[i]=1,Y[i]=0来实现。

最小耗费生成树(Kruskal)

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

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

简记为避圈加边法

最小生成树:(V , T)是G的一颗生成树,如果给G加权并且T各边的权重的和为最小值。

算法概括为

  1. 对G的边以非降序的权重排列
  2. 对于排序表中的每条边,如果加入T不会形成环路,则把它加入生成树T中,否则将它丢弃

算法KRUSKAL2

按非降序的权重将E中的边排序
for 每条边v∈ 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
  

最小耗费生成树(Prim)

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

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

N[y]是X中具有以下性质的的那个点:在所有X的邻接于y的顶点中,c[x,y]最小。也就是说N[y]是X 中离y最近的邻居。我们定义c[y]=c[y,N[y]],它是连接y和N[y]边的耗费。

算法PRIM3

T = {}; X = {1}; Y = V-{1}
for y: 2 to n
  if y邻接于1  then
    N[y]=1
    C[y]=c[1,y]
  else C[y]=∞
  end if
end for
for j: 1 to n-1 {寻找n-1条边}
  令y∈ Y,使得C[y]最小
  T = T U {(y,N[y])} {将边(y,N[y]加入到T)}
  X = X U {y}
  Y = Y - {y}
  for每个邻接于y的顶点w∈ Y
    if c[w,y]<C[w]  then
      N[w]=y
      C[w]=c[y,w]
    end if
  end for
end for

在每次迭代中,具有最小C[y]的顶点被移动到X中之后,Y中每个与y相邻的顶点w都需要更新N[w]和C[w]

文件压缩

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

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

展示的算法由Huffman提出。由该算法构造的编码满足前缀约束,并且最小化压缩文件的大小

前缀约束:一些字符的编码不能是另一个字符编码的前缀,可以防止编码的二义性

直观上来说,频度大的字符将被赋予的编码,而的编码可以赋给那些频度小的字符

算法HUFFMAN4

根据频度将所有字符插入最小堆H
V = C ; T ={}
for j: 1 to n-1
  c= DELETEMIN(H)
  c''= DELETEMIN(H)
  f(v) = f(c)+f(c'')  { v是一个新的节点 }
  INSERT(H,v)
  V = V U {v}
  T = T U {(v,c),(v,c'')}  { 使c和c''称为T中v的子节点 }
end while

  1. 在Θ( n^2 )的时间内找出s到其他每一顶点的距离长度 ↩︎

  2. 可在0( m log_n )时间内找出最小耗费生成树 ↩︎

  3. 找出最小耗费生成树需要Θ( n^2 )时间 ↩︎

  4. 时间复杂性是0(n log_n ) ↩︎

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值