最小生成樹之Prim算法實現

基本架構:先創建好一個鄰接矩陣表示的圖,然後按照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;
}


       

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章