Prim最小生成树算法
?
????? 在一個(gè)具有幾個(gè)頂點(diǎn)的連通圖G中,如果存在子圖G'包含G中所有頂點(diǎn)和一部分邊,且不形成回路,則稱G'為圖G的生成樹,代價(jià)最小生成樹則稱為最小生成樹。??????????
????? 許多應(yīng)用問題都是一個(gè)求無向連通圖的最小生成樹問題。例如:要在n個(gè)城市之間鋪設(shè)光纜,主要目標(biāo)是要使這 n 個(gè)城市的任意兩個(gè)之間都可以通信,但鋪設(shè)光纜的費(fèi)用很高,且各個(gè)城市之間鋪設(shè)光纜的費(fèi)用不同;另一個(gè)目標(biāo)是要使鋪設(shè)光纜的總費(fèi)用最低。這就需要找到帶權(quán)的最小生成樹。
????? 性質(zhì)
- 最小生成樹的邊數(shù)必然是頂點(diǎn)數(shù)減一,|E| = |V| - 1。
- 最小生成樹不可以有循環(huán)。
- 最小生成樹不必是唯一的。
Prim算法與Kruskal算法是尋找最小生成樹的經(jīng)典方法。
prim算法:
從單一頂點(diǎn)開始,普里姆算法按照以下步驟逐步擴(kuò)大樹中所含頂點(diǎn)的數(shù)目,直到遍及連通圖的所有頂點(diǎn)。
???? 為實(shí)現(xiàn)這個(gè)算法需要一個(gè)輔助數(shù)組closedge,來記錄Vnew到V-Vnew具有最小權(quán)值的邊。對(duì)于每個(gè)頂點(diǎn)vi∈V-Vnew,在輔助數(shù)組中存在一個(gè)分量closedge[i],表示vi到Vnew的最小代價(jià)邊,closedge包括兩個(gè)域, adjvex表示這條邊的頂點(diǎn),lowcost表示vi到adjvex的權(quán)值。當(dāng)選擇新的頂點(diǎn)到Vnew,選擇新的邊到Enew時(shí),要更新closedge
?無向加權(quán)圖:
Graph #include <iostream> #include <vector> #include <queue> #define MAXW 1000//定義最大權(quán)值 using namespace std; template<class T> class Graph//無向加權(quán)圖 { public:Graph();~Graph();void Create();//生成加權(quán)圖void DFSTraverse(void (*fun)(T));//深度優(yōu)先遍歷void BFSTraverse(void (*fun)(T));//廣度優(yōu)先遍歷int LocateVex(T vex);int GetVexnum(){return vexnum;}int GetArcnum(){return arcnum;}int** GetAdjMatrix(){return adjMatrix;}T GetVex(int i){return vexs[i];} private:vector<T> vexs;//頂點(diǎn)數(shù)組int** adjMatrix;//鄰接矩陣int arcnum;//弧數(shù)int vexnum;//頂點(diǎn)數(shù)bool *visited;int FirstAdjVex(int v);//v的第一個(gè)鄰接點(diǎn)int NextAdjVex(int v,int w);//從w開始找v的下個(gè)鄰接點(diǎn)void DFS(int i,void (*fun)(T)); };template<class T> Graph<T>::Graph() {adjMatrix=NULL;arcnum=0;visited=NULL; }template<class T> Graph<T>::~Graph() {for (int i=0;i<vexnum;i++){delete [] adjMatrix[i];}delete adjMatrix;adjMatrix=0;delete [] visited; }template<class T> void Graph<T>::Create() {cout<<"輸入頂點(diǎn)數(shù),弧數(shù)(以空格隔開):";cin>>vexnum;cin>>arcnum;adjMatrix=new int*[vexnum];for(int i=0;i<vexnum;i++)adjMatrix[i]=new int[vexnum];for (int i=0;i<vexnum;i++){for(int j=0;j<vexnum;j++)adjMatrix[i][j]=MAXW;//初始化鄰接矩陣 }visited=new bool[vexnum];cout<<"輸入頂點(diǎn)列,以空格隔開:";for (int i=0;i<vexnum;i++){T temp;cin>>temp;vexs.push_back(temp);//輸入頂點(diǎn) }cout<<"輸入一條邊依附的頂點(diǎn)及權(quán)值(A B 1):"<<endl;for (int i=0;i<arcnum;i++){T v1,v2;int w;cin>>v1;cin>>v2;cin>>w;int x=LocateVex(v1);int y=LocateVex(v2);adjMatrix[x][y]=w;adjMatrix[y][x]=w;//設(shè)置權(quán)值 } }template<class T> int Graph<T>::LocateVex(T vex) {for(int i=0;i<vexnum;i++){if (vexs[i]==vex){return i;}}return -1; }template<class T> int Graph<T>::FirstAdjVex(int v) {for (int i=0;i<vexnum;i++){if(adjMatrix[v][i]!=MAXW)return i;}return -1; }template<class T> int Graph<T>::NextAdjVex(int v,int w) {for (int i=w+1;i<vexnum;i++){if(adjMatrix[v][i]!=MAXW)return i;}return -1; }template<class T> void Graph<T>::DFS(int i,void (*fun)(T))//從第i個(gè)頂點(diǎn)深度優(yōu)先遍歷 {visited[i]=true;fun(vexs[i]);for (int w=FirstAdjVex(i);w>=0;w=NextAdjVex(i,w)){if(!visited[w]) DFS(w,fun);}}template<class T> void Graph<T>::DFSTraverse(void (*fun)(T)) {for(int i=0;i<vexnum;i++)visited[i]=false;for (int i=0;i<vexnum;i++){if(!visited[i])DFS(i,fun);} }template<class T> void Graph<T>::BFSTraverse(void (*fun)(T)) {queue<int> Q;for(int i=0;i<vexnum;i++)visited[i]=false;visited[0]=true;fun(vexs[0]);Q.push(0);//頂點(diǎn)入隊(duì)while (!Q.empty()){//int v=Q.back();int v=Q.front();// 出隊(duì) Q.pop();for(int w=FirstAdjVex(v);w>=0;w=NextAdjVex(v,w)){if(!visited[w]){visited[w]=true;fun(vexs[w]);Q.push(w);//訪問后頂點(diǎn)入隊(duì) }}} }?
prim算法:
template<class T> void MinSpanTree_PRIM(Graph<T> &G,T u) {//Prim算法,生成最小生成樹struct cell{T adjvex;//鄰接頂點(diǎn)int lowcost;//最小權(quán)值 };cell* closedge=new cell[G.GetVexnum()];//輔助數(shù)組int k=G.LocateVex(u);for (int i=0;i<G.GetVexnum();i++){if(i!=k){closedge[i].adjvex=u;closedge[i].lowcost=G.GetAdjMatrix()[k][i];}}closedge[k].lowcost=0;for (int i=1;i<G.GetVexnum();i++){int w=MAXW;for(int j=0;j<G.GetVexnum();j++){if(closedge[j].lowcost<w&&closedge[j].lowcost>0){w=closedge[j].lowcost;k=j;}}//輸出路徑cout<<endl;cout<<"找到路徑:"<<closedge[k].adjvex<<"----"<<G.GetVex(k)<<"權(quán)值:"<<w<<endl;closedge[k].lowcost=0;for(int j=0;j<G.GetVexnum();j++){//更新closedge[j]if (G.GetAdjMatrix()[k][j]<closedge[j].lowcost){closedge[j].adjvex=G.GetVex(k);closedge[j].lowcost=G.GetAdjMatrix()[k][j];}}}}main:
void printfun(char ch) {cout<<ch<<" "; } int main() {Graph<char> G;G.Create();cout<<"深度優(yōu)先遍歷:";G.DFSTraverse(printfun);cout<<endl<<"廣度優(yōu)先遍歷:";G.BFSTraverse(printfun);MinSpanTree_PRIM(G,G.GetVex(0));return 1;}?
?例子:
原圖:
運(yùn)行結(jié)果:
?
轉(zhuǎn)載于:https://www.cnblogs.com/wonderKK/archive/2012/04/12/2444571.html
總結(jié)
以上是生活随笔為你收集整理的Prim最小生成树算法的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: swift下FMDB的使用
- 下一篇: 编程挑战(6)