天天看點

最小生成樹kruskal算法python實作

#File Name : 最小生成樹kruskal算法.py
#思路 邊權重從小到大排序 從權重小的邊開始
#不形成回路就要,不然不要。直至包含所有點

#File Name : 并查集.py

# 并查集結構
from heapq import  *
class Node(object):
    pass
class UnionFindSet(object):
    def __init__(self,nodes):
        self.fatherDict = {}
        # key node  value father 一層一層向上找
        self.sizeDict = {}
        # key 節點  value 節點所在集合共有多少個節點
        for node in nodes:
            self.fatherDict[node]= node
            self.sizeDict[node] = 1
        #每個節點的父親是自己 并且所在的集合為個數為1
        #因為要少挂多 ,是以要找節點數目
    def FindHead(self,node):
        stack = []
        father = self.fatherDict[node]
        while father!=node:
            stack.append(node)
            node = father
            father = self.fatherDict[node]
        while stack:
            self.fatherDict[stack.pop()] = father
        return father
    def isSameSet(self,a,b):
        return self.FindHead(a) == self.FindHead(b)
    def uion(self,a,b):
        if a is None or b is None:
            return
        aHead = self.FindHead(a)
        bHead = self.FindHead(b)
        if aHead!=bHead:
            asize = self.sizeDict[aHead]
            bsize = self.sizeDict[bHead]
            if asize<=bsize:
                self.fatherDict[aHead] = bHead
                self.sizeDict[bHead] = asize+bsize
            else:
                self.fatherDict[bHead] = aHead
                self.sizeDict[aHead] = asize+bsize

class Node(object):
    def __init__(self,value=None):
        self.value = value #節點的值
        self.come = 0 #節點入度
        self.out = 0 #節點出度
        self.nexts = [] #節點的鄰居節點
        self.edges = [] #在節點為from的情況下,邊的集合
class Edge(object):
    def __init__(self,weight=None,fro,to):
        self.weight = weight # 邊的權重
        self.fro = fro # 邊的from節點
        self.to = to #邊的to節點
    def __lt__(self, other):
        return self.weight<other.weight
class Graph(object):
    def __init__(self):
        self.nodes = {} #圖所有節點的集合  字典形式 :{節點編号:節點}
        self.edges = [] #圖的邊集合

def creatGraph(matrix):
    # 二維數組matrix [權重  從那個點的值  去哪個點的值]
    graph = Graph()
    # 建立所有節點
    for edge in matrix:
        weight = edge[0]
        fro = edge[1]
        to = edge[2]
        if fro not in graph.nodes:
            graph.nodes[fro] = Node(fro)
        if to not in graph.nodes:
            graph.nodes[to] = Node(to)
    #建立所有的邊
        fromNode = graph.nodes[fro]
        toNode = graph.nodes[to]
        newEdge = Edge(weight,fromNode,toNode)
        fromNode.nexts.append(toNode) #加上鄰居指向
        fromNode.out+=1 #出度+1
        toNode.come+=1 #to 的入度+1
        fromNode.edge.append(newEdge) #邊的集合+1
        graph.edges.append(newEdge)

    return graph
#k算法  堆結構  并查集結構  圖結構
def kruskalMST(graph):
    unionfind = UnionFindSet(graph.nodes.values())
    heapq = []
    for edge in graph.edges:
        heappush(heapq,edge)
    res = set()
    while len(heapq)>0:
        edge = heappop(heapq)
        if unionfind.isSameSet(edge.fro,edge.to)==False:
            res.add(edge)
            unionfind.uion(edge.fro,edge.to)
    return res