最小生成樹-----Kruskal算法和Prim算法,python


最小生成樹的兩種算法python語言

MAX=999999#定義最大數
class Start(object):#創建類
    def __init__(self,lin,n):#基類對象,在這里用於傳入參數和初始化類
        self.lin=lin#傳入鄰接矩陣
        self.n=n#傳入節點總個數
        self.bian=self.get_bian()#根據鄰接矩陣,獲得無向連接圖的邊數
    def get_bian(self):#類中的獲取邊數的方法
        count=0#初始化邊數變量
        for i in range(self.n):#循環遍歷整個鄰接矩陣獲得邊數
            for j in range(i):#內循環
                if self.lin[i][j]!=0 and self.lin[i][j]!=-1:#如果不是本身(!=0)或者不連接(!=-1)則為一條邊
                    count+=1#符合條件邊數加1
        return count#返回邊數
    def Prim(self):#Prim算法
        s=[0]#記錄已經存在與最小生成樹的節點
        o=[i for i in range(1,self.n)]#將每一個節點分開存放方便遍歷
        quan=0#總權重
        rex=[]#結果列表
        while len(o)>0:#循環生成最小生成樹
            dian1,dian2,temp=0,0,MAX#定義標志變量=0代表自身,=MAX代表不連通
            for j in s:#遍歷已經存在於最小生成樹的節點
                for i in o:#遍歷每不存在於最小生成樹的節點
                    if self.lin[j][i]==-1 or self.lin[j][i]==0:#如果連兩個節點不連通,繼續循環
                        continue#繼續循環
                    else:##如果聯通
                        if temp>self.lin[j][i]:#選擇存在於最小生成樹和不存在於最小生成樹的兩個節點中邊權最小的節點
                            temp=self.lin[j][i]#中間變量存儲最小邊權
                            dian1=i#中間變量不存在於最小生成樹的點
                            dian2=j#中間變量存在於最小生成樹的點
            quan+=temp#計算總邊權
            rex.append([dian2,dian1,temp])#將此節點存於結果中
            s.append(dian1)#將不存在於最小生成樹的節點插入到最小生成樹的節點
            o.remove(dian1)#在不存在於最小生成樹的列表中刪除此節點
        rex.append(quan)#將總邊權插入到最終結果
        return rex#返回
    def Kruskal(self):#Kruskal算法
        s=0#初始化總邊權
        rex=[]#定義最小生成樹的每一條邊的列表
        a=[]#定義邊的列表
        for i in range(self.n):#循環遍歷整個鄰接矩陣
            for j in range(self.n):#內循環
                if self.lin[i][j]!=-1 and self.lin[i][j]!=0:#如果不是本身(!=0)或者不連接(!=-1)則為一條邊
                    a.append([i,j,self.lin[i][j]])#將邊以兩個節點和一個邊權的格式存儲
        a.sort(key=lambda a:a[2])#對每個邊以邊權排序
        group=[[i] for i in range(self.n)]#初始化,將每個節點看作一個連通分支
        for e in a:#循環遍歷邊的列表
            for i in range(group.__len__()):#循環遍歷每個連通分支
                if e[0] in group[i]:#判斷這個邊的一個節點是否在這個連通分支內
                    m=i#如果是記錄下來
                if e[1] in group[i]:#判斷這個邊的另一個節點是否在這個連通分支內
                    n=i#如果是記錄下來
            if m!=n:#如果這條邊的兩個節點在兩個連通分支內,則可以選擇此邊
                rex.append(e)#將結果儲存
                s+=e[2]#計算總邊權
                group[m]=group[m]+group[n]#將兩個連通分支合並
                group[n]=[]#將另一個聯通分支清空
        rex.append(s)#將總邊權加入到結果列表
        return rex#返回
if __name__=="__main__":
    n=int(input("請輸入節點個數:"))#輸入節點個數
    lin=[]#定義鄰接矩陣的列表
    for i in range(n):#循環輸入鄰接矩陣
        print("請輸入鄰接矩陣第",i+1,"行:(每個元素以 空格 隔開,自身為 0,兩點之間無直線連接為 -1)")#以行為單位一行一行輸入
        q=input()#用變量接受輸入的字符串
        q=q.split(" ")#將字符串轉化為列表
        q=list(map(int,q))#將列表中的字符串轉化為int類型
        lin.append(q)#將輸入的每一行加入到鄰接矩陣中
    print("您輸入的鄰接矩陣為:")#輸出用戶輸入的鄰接矩陣,用於用戶檢驗錯誤
    for i in lin:#循環一行一行輸出
        print(i)#輸出
    print("開始Prim算法...")#提示語句
    start=Start(lin,n)#創建類的對象
    qq=start.Prim()#調用類中Prim方法,開始進行Prim生成最小生成樹
    print("Prim最小生成樹為:(每一個[]為一條邊,[開始點,結束點,權],最后一個數為總權重)")#輸出Prim最小生成樹結果
    print(qq)#輸出
    print("-----------------------------------------------------------------------------------------------------")#分隔符
    print("開始Kruskal算法...")#提示語句
    pp=start.Kruskal()#開始Kruskal算法
    print("Kruskal最小生成樹為:(每一個[]為一條邊,[開始點,結束點,權],最后一個數為總權重)")#輸出結果
    print(pp)#輸出

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM