最小生成树(Python实现)--kruskal算法、prim算法、破圈法

1.避圈法(Kruskal算法–加边法)
克鲁斯克尔算法原理:
按照边的从小到大取边,并入边的两个节点,在这个过程中保证并入边后不构成圈,因此也称避圈法。
算法过程:
1)先对边按权重从小到大排序;
2)取权重最小的一条边,若该边两个节点均为不同分量,则加入最小生成树;
3)以此类推,直至遍历完所有的边。
2.prim算法–加点法
算法过程:
将所有节点划分为两类:selected_node和candidate_node
1)任取一节点加入selected_node,遍历头结点在selected_node,尾节点在candidate_node的边,选取符合条件的权重最小的边,加入最小生成树;
2)将边的尾节点加入selected_node中,并在candidate_node中删除,直至candidate_node中无节点。循环条件为:所有节点都有边连接
3.破圈法实现最小生成树
在克鲁斯克尔算法基础上,我国著名数学家管梅谷教授于1975年提出了最小生成树的破圈法。
算法过程:
1)先将所有的边按权值进行降序排列.
2)之后对于取出的每一个边来说,判断其连接的两个结点是否具有圈.(即先删除次边,然后判断这两个结点是否连接,之后对删除的边进行恢复)
3)对于有圈的,将这条边删除,否则,往下查找.
4)算法结束条件:剩下的边=结点数-1.

import networkx as nx
import matplotlib.pyplot as plt
import numpy as np
from numpy import random
import copy



G = nx.Graph()
Matrix= np.array(random.randint((10),size=(10,10)))
# print(maps)
for i in range(len(Matrix)):
    for j in range(len(Matrix)):
        if Matrix[i, j]!= 0:
          G.add_edge(i, j)
nx.draw_networkx(G)
plt.title("G")
plt.show()

class Graph(object):
    def __init__(self, Matrix):
        self.Matrix = Matrix
        self.nodenum = self.get_nodenum()
        self.edgenum = self.get_edgenum()

    def get_nodenum(self):
        return len(self.Matrix)

    def get_edgenum(self):
        count = 0
        for i in range(self.nodenum):
            for j in range(i):
                if self.Matrix[i][j] > 0 and self.Matrix[i][j] < 9999:
                    count += 1
        return count

    def kruskal(self):
        list = []
        if self.nodenum <= 0 or self.edgenum < self.nodenum - 1:
            return list

        edge_list = []
        for i in range(self.nodenum):
            for j in range(i, self.nodenum):
                if self.Matrix[i][j] < 9999:
                    edge_list.append([i, j, self.Matrix[i][j]])
        edge_list.sort(key=lambda a: a[2])  # 已经排好序的边集合

        group = [[i] for i in range(self.nodenum)]#列表解析:根据已有列表,高效创建新列表的方式
        for edge in edge_list:
            for i in range(len(group)):
                if edge[0] in group[i]:
                    m = i
                if edge[1] in group[i]:
                    n = i
            if m != n:
                list.append(edge)
                group[m] = group[m] + group[n]
                group[n] = []
        return list

    def prim(self):
        list = []
        if self.nodenum <= 0 or self.edgenum < self.nodenum - 1:
            return list

        selected_node = [0]
        candidate_node = [i for i in range(1, self.nodenum)]
        while len(candidate_node) > 0:
            begin, end, minweight = 0, 0, 9999
            for i in selected_node:
                for j in candidate_node:
                    if self.Matrix[i][j] < minweight:
                        minweight = self.Matrix[i][j]
                        begin = i
                        end = j
            list.append([begin, end, minweight])
            selected_node.append(end)
            candidate_node.remove(end)
        return list

    


G = Graph(Matrix)
print('邻接矩阵为\n%s'%G.Matrix)
print('节点数据为%d,边数为%d\n'%(G.nodenum, G.edgenum))
print('------最小生成树kruskal算法------')
print(G.kruskal())

print('------最小生成树prim算法')
print(G.prim())



最小生成树(Python实现)--kruskal算法、prim算法、破圈法_第1张图片
最小生成树(Python实现)--kruskal算法、prim算法、破圈法_第2张图片
在这里插入图片描述
破圈法Python实现

def break_circle(self):
    parents = []

    def init(parents):
        for n in range(self.numVertices):
            parents.append(n)

    def find(i):
        while (i != parents[i]):
            i = parents[i]
        return i

    def union(i, j):
        if (find(i) == find(j)):
            return
        else:
            parents[find(i)] = find(j)

    def isconnected(i, j):
        return find(i) == find(j)

    def reunion(aGraph):
        parents.clear()
        init(parents)
        for edge in self.edgeList:
            union(edge[0], edge[1])

    reunion(self)

    self.edgeList.sort(key=lambda x: x[2], reverse=True)
    n = self.numEdges
    for x in range(n):
        edge = self.edgeList.pop(0)
        reunion(self)
        bool = isconnected(edge[0], edge[1])
        if bool:
            self.numEdges = self.numEdges - 1
        else:
            self.edgeList.append(edge)
            reunion(self)
    print(self.edgeList)

你可能感兴趣的:(图论)