基本架構:先創建好一個鄰接矩陣表示的圖,然後按照prim算法思想找到最小生成樹,注意將鄰接矩陣表示的圖在求最小生成樹的時候轉化爲鄰接表。
Prim 算法思想:
void Prim()
{
MST={V0};
while(1)
{
v=未收錄頂點中dist最小的一個;
if(這樣的v不存在)
break;
將v收錄進MST中:dist[V]=0;
for(v的每個鄰接點W)
{
if(dist[W]!=0)
if(E(v,w)<dist[W])
{
dist[W]=E(v,w);
parent[w]=v;
}
}
}
if(MST中的頂點個數小於|V|個)
cout<<"該圖爲非連通圖!"<<endl;
}
代碼實現:
// Prim最小生成樹實現.cpp : 定義控制檯應用程序的入口點。
//
#include "stdafx.h"
#include<iostream>
#include<stdio.h>
#include<malloc.h>
#define MaxVertexNum 100
#define INFINITY 50
using namespace std;
typedef int Vertex;
typedef int WeightType;
typedef char DataType;
//邊的定義,適合鄰接矩陣和鄰接表
typedef struct ENode *PtrToENode;
struct ENode
{
Vertex V1, V2;
WeightType Weight;
};
typedef PtrToENode Edge;
//鄰接矩陣表示的圖的建立
typedef struct MGNode *PtrToMGNode;
struct MGNode
{
int Nv;//頂點數
int Ne;//邊數
WeightType G[MaxVertexNum][MaxVertexNum]; //鄰接矩陣
DataType Data[MaxVertexNum];//頂點數組
};
typedef PtrToMGNode MGraph;
//鄰接表表示的圖的結構體定義
//鄰接點的定義
typedef struct AdjVNode *PtrToAdjVNode;
struct AdjVNode
{
Vertex AdjV; //鄰接點下標
WeightType Weight; //邊權重
PtrToAdjVNode Next; //指向下一個鄰接點的指針
};
//點表頭結點的定義
typedef struct Vnode
{
PtrToAdjVNode FirstEdge; //邊表頭指針
DataType Data; //存頂點數據
}AdjList[MaxVertexNum];
//圖結點的定義
typedef struct LGNode *PtrToLGNode;
struct LGNode
{
int vexnum;
int edgenum;
AdjList G; //鄰接表
};
typedef PtrToLGNode LGraph;
int visited[MaxVertexNum];//標誌數組
//函數聲明
LGraph CreateLGraph(int Vertexnum);
void InsertLEdge(LGraph Graph, Edge E);
LGraph BuildLGraph();
void DFSTravel(LGraph Graph, Vertex V);
//函數定義
LGraph CreateLGraph(int Vertexnum)
{//初始化一個只有頂點,沒有邊的圖
Vertex V;
LGraph Graph;
Graph = (LGraph)malloc(sizeof(struct LGNode));
Graph->vexnum = Vertexnum;
Graph->edgenum = 0;
for (V = 0; V<Graph->vexnum; V++)
{
Graph->G[V].FirstEdge = NULL;
}
return Graph;
}
void InsertLEdge(LGraph Graph, Edge E)
{
PtrToAdjVNode NewNode;
//插入邊<v1,v2>
//爲v2建立新的表結點
NewNode = (PtrToAdjVNode)malloc(sizeof(struct AdjVNode));
NewNode->AdjV = E->V2;
NewNode->Weight = E->Weight;
NewNode->Next = Graph->G[E->V1].FirstEdge;
Graph->G[E->V1].FirstEdge = NewNode;
//若是無向圖,還需插入邊<v2,v1>
//爲v1建立新的結點
NewNode = (PtrToAdjVNode)malloc(sizeof(struct AdjVNode));
NewNode->AdjV = E->V1;
NewNode->Weight = E->Weight;
NewNode->Next = Graph->G[E->V2].FirstEdge;
Graph->G[E->V2].FirstEdge = NewNode;
}
LGraph BuildLGraph()
{
LGraph Graph;
Edge E;
Vertex V;
int vexnum, i;
std::cout << "請輸入頂點個數:";
cin >> vexnum;
Graph = CreateLGraph(vexnum);
std::cout << "請輸入邊的個數:";
cin >> Graph->edgenum;
if (Graph->edgenum != 0)
{
E = (Edge)malloc(sizeof(struct ENode));
for (i = 0; i<Graph->edgenum; i++)
{
cin >> E->V1 >> E->V2 >> E->Weight;
InsertLEdge(Graph, E);
}
}
//如果頂點有數據的話,讀入數據
for (V = 0; V<Graph->vexnum; V++)
cin >> Graph->G[V].Data;
std::cout << "創建好的鄰接表輸出如下所示:" << endl;
for (V = 0; V<Graph->vexnum; V++)
{
PtrToAdjVNode W;
std::cout << Graph->G[V].Data << "的鄰接點:";
for (W = Graph->G[V].FirstEdge; W; W = W->Next)
{
std::cout << W->AdjV << "," << Graph->G[W->AdjV].Data << "," << W->Weight << " ";
}
std::cout << endl;
}
return Graph;
}
//深度優先遍歷圖
/*void DFSTravel(LGraph Graph, Vertex V)
{
PtrToAdjVNode W;
cout << Graph->G[V].Data;
visited[V] = 1;
for (W = Graph->G[V].FirstEdge; W; W = W->Next)
if (!visited[W->AdjV])
DFSTravel(Graph, W->AdjV);
}*/
//鄰接矩陣表示的圖的實現
MGraph CreateMGraph(int Vertexnum)
{//初始化一個有Vertexnum個頂點但沒有變得圖
Vertex V, W;
MGraph Graph;
Graph = (MGraph)malloc(sizeof(struct MGNode));
Graph->Nv = Vertexnum;
Graph->Ne = 0;
for (V = 0; V<Graph->Nv; V++)
{
for (W = 0; W<Graph->Nv; W++)
Graph->G[V][W] = INFINITY;
//如果是有權無向圖,應該是
//Graph->G[V][W] =Graph->G[W][V] = INFINITY;
//如果是無權圖有向圖,可以初始化爲0;
//Graph->G[V][W] = 0;
//如果是無權無向圖,應該是
//Graph->G[V][W] =Graph->G[W][V] = 0;
}
return Graph;
}
void InsertMEdge(MGraph Graph, Edge E)
{//插入邊
Graph->G[E->V1][E->V2] = E->Weight;
//若是無向圖,則需要插入這條邊
Graph->G[E->V2][E->V1] = E->Weight;
//若是無權有向圖,
//Graph->G[E->V1][E->V2]=1;
//若是無權無向圖,
///Graph->G[E->V2][E->V1] = 1;
}
MGraph BuildMGraph()
{
MGraph Graph;
Edge E;
Vertex V;
int i;
int Nv;
std::cout << "請輸入頂點個數:";
cin >> Nv;
Graph = CreateMGraph(Nv);
std::cout << "請輸入邊的個數:";
cin >> Graph->Ne;
if (Graph->Ne != 0)
{
E = (Edge)malloc(sizeof(struct ENode));
for (i = 0; i<Graph->Ne; i++)
{
cin >> E->V1 >> E->V2 >> E->Weight;
//如果是無權圖
//cin>>E->V1>>E->V2;
InsertMEdge(Graph, E);
}
}
for (V = 0; V<Graph->Nv; V++)
cin >> Graph->Data[V];
Vertex W;
std::cout << "創建好的鄰接矩陣如下所示:" << endl;
for (V = 0; V<Graph->Nv; V++)
{
for (W = 0; W < Graph->Nv; W++)
std::cout << Graph->G[V][W] << " ";
std::cout << endl;
}
return Graph;
}
Vertex FindMinDist(MGraph Graph, WeightType dist[])
{
Vertex MinV, V;
WeightType MinDist = INFINITY;
for (V = 0; V<Graph->Nv; V++)
{
if (dist[V] != 0 && dist[V]<MinDist)
{
MinDist = dist[V];
MinV = V;
}
}
if (MinDist<INFINITY)
return MinV;
else
return -1;
}
void Prim(MGraph Graph, LGraph MST)
{
WeightType dist[MaxVertexNum], TotalWeight;
Vertex parent[MaxVertexNum], V, W;
int VCount;
Edge E;
//初始化,默認初始化定點下標爲0
for (V = 0; V<Graph->Nv; V++)
{
dist[V] = Graph->G[0][V];
parent[V] = 0;
}
TotalWeight = 0;
VCount = 0;
//創建包含所有頂點但沒有邊的圖,用鄰接表表示
MST = CreateLGraph(Graph->Nv);
E = (Edge)malloc(sizeof(struct ENode));
//將初始點0收錄到MST
dist[0] = 0;
VCount++;
parent[0] = -1;
while (1)
{
V = FindMinDist(Graph, dist);
if (V == -1)
break;
//將V及其相應的邊<parent[V],V>收錄進MST
E->V1 = parent[V];
E->V2 = V;
E->Weight = dist[V];
InsertLEdge(MST, E);
TotalWeight += dist[V];
dist[V] = 0;
VCount++;
for (W = 0; W<Graph->Nv; W++)
{
if (dist[W] != 0 && Graph->G[V][W]<INFINITY)
//若W是v的鄰接點,且沒有被收錄
{
if (Graph->G[V][W]<dist[W])
{
dist[W] = Graph->G[V][W];
parent[W] = V;
}
}
}
}
if (VCount<Graph->Nv)
{
TotalWeight = -1;
}
std::cout << "最小生成樹的總權值:" << TotalWeight << endl;
std::cout << "輸出創建好的最小生成樹的鄰接表表示:" << endl;
for (V = 0; V<MST->vexnum; V++)
{
PtrToAdjVNode W;
std::cout << V<< "的鄰接點:";
for (W = MST->G[V].FirstEdge; W; W = W->Next)
{
std::cout << W->AdjV<< "," << W->Weight << " ";
}
std::cout << endl;
}
}
int _tmain(int argc, _TCHAR* argv[])
{
MGraph Graph;
LGraph MST = NULL;
Graph = BuildMGraph();
Prim(Graph, MST);
return 0;
}