最小生成树之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;
}


       

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