您的位置:首页 > 其它

最小生成树之Prim算法实现

2016-06-07 21:03 441 查看
基本架构:先创建好一个邻接矩阵表示的图,然后按照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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息