📅  最后修改于: 2023-12-03 15:41:49.535000             🧑  作者: Mango
贪婪算法是一种贪心思想,即每一步选择当前局部最优解,最终得到的就是全局最优解。它的一般结构如下:
初始化:选择最基本的信息,对问题进行初步处理。
重复执行以下步骤直到满足目标:
选择当前状态下的局部最优解。
根据所选解,修改问题的约束条件。
判断问题是否已经满足终止条件,如果满足,则停止算法。
贪婪算法主要适用于满足“无后效性”的问题,即某个状态以后的过程不会影响以前做出的决策。以下是几个贪婪算法的应用示例。
最小生成树(Minimum Spanning Tree)的问题是:在一个带权连通图中找一棵生成树,使得树的权值之和最小。
Kruskal算法是一种贪心算法,它的主要思想是从小到大选择边,加入到生成树中,如果加入该边会形成环,则不加入该边。
代码示例:
def Kruskal(Graph):
parent = dict()
rank = dict()
def make_set(vertex):
parent[vertex] = vertex
rank[vertex] = 0
def find(vertex):
if parent[vertex] != vertex:
parent[vertex] = find(parent[vertex])
return parent[vertex]
def union(vertex1, vertex2):
root1 = find(vertex1)
root2 = find(vertex2)
if root1 != root2:
if rank[root1] > rank[root2]:
parent[root2] = root1
else:
parent[root1] = root2
if rank[root1] == rank[root2]: rank[root2] += 1
for vertex in Graph['vertices']:
make_set(vertex)
MST = set()
edges = list(Graph['edges'])
edges.sort()
for edge in edges:
weight, vertex1, vertex2 = edge
if find(vertex1) != find(vertex2):
union(vertex1, vertex2)
MST.add(edge)
return MST
背包问题(Knapsack Problem)是指给定一个背包容量以及物品列表,每个物品都有一个重量和一个价值,要求从中选出一些物品放入背包中,使得放入的物品重量之和不超过背包容量,同时让背包中物品的价值最大。
贪心算法在背包问题中的应用是:按照单位价值排序,将价值最大的放入背包中,直至背包不能再放任何物品为止。
代码示例:
def knapsack(weights, values, capacity):
n = len(weights)
ratios = [(values[i] / weights[i], weights[i], values[i]) for i in range(n)]
ratios.sort(reverse=True)
total = 0
for r in ratios:
if capacity == 0:
break
if r[1] <= capacity:
total += r[2]
capacity -= r[1]
else:
total += r[0] * capacity
capacity = 0
return total
哈夫曼编码(Huffman Coding)是一种可变长度编码(Variable Length Code),它的主要优势是在固定长度的编码之上,使得出现次数多的字符使用的编码较短。这将减少存储空间、传输成本以及处理时间。
哈夫曼编码的贪心思想是:将出现概率最小的两个字符合并为一个新的字符,其出现概率为这两个字符的出现概率之和。重复以上步骤直到只剩下一个字符。
代码示例:
from queue import PriorityQueue
from typing import Tuple
def huffman(symbols: str, frequencies: Tuple[int]) -> Tuple[Dict[str, str], str]:
queue = PriorityQueue()
for i, symbol in enumerate(symbols):
queue.put((frequencies[i], symbol))
while queue.qsize() > 1:
left = queue.get()
right = queue.get()
for symbol in left[1]:
self.encoding[symbol] += '0'
for symbol in right[1]:
self.encoding[symbol] += '1'
queue.put((left[0] + right[0], left[1] + right[1]))
root = queue.get()
return self.encoding, root[1]
贪婪算法的效率通常很高,但它只考虑当前状态下的局部最优解,不能保证一定得到全局最优解。应用贪婪算法时,需要确保问题满足无后效性、最优子结构性质,并且算法的“贪心策略”需要经过严谨的证明。