用於最小產生樹的Prim演算法實現

來源:互聯網
上載者:User

Prim演算法,同Kruskal演算法一樣,也是解決最小產生樹的演算法。在講這個演算法前,我們先來看看其他的一些概念。

什麼是割?在無向圖中,割指的是對圖的一種劃分。當一條邊(u,v)的一個頂點屬於S,另一個頂點屬於V-S,則我們稱(u,v)邊通過割(S,V-S)。如果一個邊的集合A中沒有任何一條邊通過割,則我們稱該割不妨害邊集A。如果某條邊的權值在通過某個割的所有邊中是最小的,則稱該邊是通過該割的一條輕邊。

Prim演算法的基本思想就是不斷的尋找通過一條割的輕邊,這個割是指當前最小產生樹所組成的點集S和圖中不在最小產生樹中的點集(V-S)所形成的一種圖的劃分,然後將所找到的輕邊添加到最小產生樹中。我們使用最小優先隊列來快速的尋找通過某個割的輕邊。當然,我們在尋找輕邊的時候要檢查該邊的兩個頂點是否已經在最小產生樹中,如果在的話,我們就不需要再將這條邊添加到最小產生樹的邊集了,因為這兩個端點已經是連通著的了。

代碼實現如下所示:

package com.chapter4;

//用於解決最小產生樹問題的Prim演算法(延時版本)

import java.util.Queue;

import java.util.LinkedList;

public class LazyPrimMST {

         privateQueue<Edge> mst;

         private boolean[]marked;

         private doubletotalweight;

         privateMinPriorityQueue<Edge> mpq;

        

         publicLazyPrimMST(EdgeWeightedGraph G)

         {

                   int V=G.V();

                   mst=newLinkedList<Edge>();

                   marked=newboolean[V];

                   mpq=newMinPriorityQueue<Edge>();

                   for(inti=0;i<V;i++)

                   {

                            if(!marked[i])

                                     prim(G,i);

                   }

         }

         private voidprim(EdgeWeightedGraph G,int s)

         {

                   scan(G,s);

                   while(!mpq.isEmpty())

                   {

                            Edgee=mpq.deleteMin();

                            System.out.println("從優先隊列中移除"+e);

                            intv=e.either(),w=e.other(v);

                            assertmarked[v]||marked[w];

                            if(marked[v]&&marked[w])continue;

                            mst.add(e);

                            System.out.println("向最小產生樹的邊集合中加入"+e);

                            totalweight+=e.weight();

                            if(!marked[v])scan(G,v);

                            if(!marked[w])scan(G,w);

                   }

         }

        

         private voidscan(EdgeWeightedGraph G,int v)

         {

                   assert!marked[v];

                   marked[v]=true;

                   for(Edgee:G.adj(v))

                   {

                            if(!marked[e.other(v)])

                            {

                                     mpq.insert(e);

                                     System.out.println("向優先隊列中加入"+e);

                            }

                   }

         }

        

         public doubletotalWeight(){return totalweight;}

        

         public StringtoString()

         {

                   StringBuildersb=new StringBuilder();

                   sb.append("最小產生樹的邊資訊:\n");

                   for(Edgee:mst)

                   {

                            sb.append(e.toString()+"\n");

                   }

                   sb.append(String.format("權值和為:%.5f",totalweight));

                   returnsb.toString();

         }

        

         public static voidmain(String[] args) {

                   // TODOAuto-generated method stub

                   In in=newIn("tinyEWG.txt");

                   EdgeWeightedGraphgraph=new EdgeWeightedGraph(in);

                   LazyPrimMSTsample=new LazyPrimMST(graph);

                   System.out.println(sample);

         }

}

運行結果如下所示:

 

向優先隊列中加入0--7[0.16000]

向優先隊列中加入0--4[0.38000]

向優先隊列中加入0--2[0.26000]

向優先隊列中加入6--0[0.58000]

從優先隊列中移除0--7[0.16000]

向最小產生樹的邊集合中加入0--7[0.16000]

向優先隊列中加入4--7[0.37000]

向優先隊列中加入5--7[0.28000]

向優先隊列中加入1--7[0.19000]

向優先隊列中加入2--7[0.34000]

從優先隊列中移除1--7[0.19000]

向最小產生樹的邊集合中加入1--7[0.19000]

向優先隊列中加入1--5[0.32000]

向優先隊列中加入1--2[0.36000]

向優先隊列中加入1--3[0.29000]

從優先隊列中移除0--2[0.26000]

向最小產生樹的邊集合中加入0--2[0.26000]

向優先隊列中加入2--3[0.17000]

向優先隊列中加入6--2[0.40000]

從優先隊列中移除2--3[0.17000]

向最小產生樹的邊集合中加入2--3[0.17000]

向優先隊列中加入3--6[0.52000]

從優先隊列中移除5--7[0.28000]

向最小產生樹的邊集合中加入5--7[0.28000]

向優先隊列中加入4--5[0.35000]

從優先隊列中移除1--3[0.29000]

從優先隊列中移除1--5[0.32000]

從優先隊列中移除2--7[0.34000]

從優先隊列中移除4--5[0.35000]

向最小產生樹的邊集合中加入4--5[0.35000]

向優先隊列中加入6--4[0.93000]

從優先隊列中移除1--2[0.36000]

從優先隊列中移除4--7[0.37000]

從優先隊列中移除0--4[0.38000]

從優先隊列中移除6--2[0.40000]

向最小產生樹的邊集合中加入6--2[0.40000]

從優先隊列中移除3--6[0.52000]

從優先隊列中移除6--0[0.58000]

從優先隊列中移除6--4[0.93000]

最小產生樹的邊資訊:

0--7[0.16000]

1--7[0.19000]

0--2[0.26000]

2--3[0.17000]

5--7[0.28000]

4--5[0.35000]

6--2[0.40000]

權值和為:1.81000

(說明:程式中需要的其他一些類可以在“用於最小產生樹的Kruskal演算法實現”一文中查到,在這篇文章中不在重複!)

文章連結: http://blog.csdn.net/andamajing/article/details/8702179點擊開啟連結

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.