算法教程学习——贪心算法(Kruskal算法)

贪心算法所做的每个选择都是独立的,并且是当下所有选择中的最佳决策。贪心算法相对容易实现,但是很难给出一个确切的证明,即贪心算法是合理的,是问题的最优解之一。贪心算法的证明通常涉及到两个步骤:

  1. 贪心选择性
  2. 最优子结构

贪心选择性指的是,每次通过贪心选择得到了一个最优解决方案的一部分。而最优子结构则是,做出选择后剩下的问题和原有的问题有着同样的解决方案。

最小生成树问题

Kruskal算法

kruskal算法的思想是,按照所有边的大小排序,从最短边开始选择,依次加入最短边,如果未出现环,则算法继续,出现环则跳过该边,算法继续,直到遍历完边集合。
这里的贪心就体现在每次都选择当前最短的边作为生成树的元素。这种贪心的想法是正确的,接下来要处理的问题就是如何判断环的问题。一种简单的解决方案就是运用遍历技术,另外还可以运用并查集来解决问题。
关于并查集,可以参考这篇博客:https://blog.csdn.net/huisekonghuan/article/details/79288550

#coding:utf-8

class unionFindSet(object):
	
	def init(self, number):
		self.parent = [i for i in range(number)]

	def find(self, k):
		while self.parent[k] != k:
			k = self.parent[k]

		return k

	def union(self ,u, v):
		if self.isConnected(u, v) is False:
			self.parent[u] = v 

	def isConnected(self, u, v):
		u = self.find(u)
		v = self.find(v)
		if u == v:
			return True
		return False


def takeEdge(elem): 
	return elem[2] 

if __name__ == "__main__":
	edge = [[0,1,1],[0,3,3],[0,2,2],[1,2,1],[1,3,4],[2,3,2]]

	edge.sort(key = takeEdge)

	x = unionFindSet()
	x.init(4)
	for elem in edge:
		u = elem[0]
		v = elem[1]
		x.union(u, v)

	print(x.parent)

这里使用并查集结构,就是用来判断将加入边的两个节点是否存在于同一个子最小生成树中。
算法教程学习——贪心算法(Kruskal算法)_第1张图片
答案输出结果:
在这里插入图片描述
列表的第几位代表了从哪个节点通往哪个节点,这里是按照单向来计算的。
答案意思是0–>1–>2–>3–>3,相同节点表示没有其他出边了。
算法教程学习——贪心算法(Kruskal算法)_第2张图片

你可能感兴趣的:(经典算法)