最小生成树
//graph.h
#include<iostream>
#include<cstdlib>
#include<queue>
using namespace std;
#define maxVert 20
#define maxWeight 10000
typedef char VType;
typedef double WType;
typedef struct{
int numVetr,numEdges;//点和边的个数
VType *VertList;//点矩阵
WType **Edge;//邻接矩阵
}Graph;
void InitGraph(Graph &G)//对邻接矩阵表示的图进行初始化
{
int i,j;
G.numEdges=0;
G.numVetr=0;
G.VertList=new VType[maxVert];
if(G.VertList==NULL)
{cout<<"Error"<<endl;exit(0);}
G.Edge=new WType*[maxVert];
if(G.Edge==NULL)
{cout<<"Error"<<endl;exit(0);}
for(i=0;i<maxVert;i++)
{
G.Edge[i]=new WType[maxVert];
if(G.Edge[i]==NULL)
{cout<<"Error"<<endl;exit(0);}
}
for(i=0;i<maxVert;i++)
{
G.VertList[i]=0;
for(j=0;j<maxVert;j++)
G.Edge[i][j]=(i==j)?0:maxWeight;
}
}
int NumberOfVert(Graph G)
{
return G.numVetr;
}
int NumberOfEdges(Graph G)
{
return G.numEdges;
}
int GetVertPos(Graph G,VType vert)//重顶点的数据值找到该顶点的顶点号
{
for(int i=0;i<G.numVetr;i++)
if(G.VertList[i]==vert)
return i;
return -1;
}
VType GetValue(Graph G,int i)//返回顶点i的值,若i不合理则返回0
{
if(i<0||i>=G.numVetr)
return 0;
else
return G.VertList[i];
}
WType GetWeight(Graph G,int v1,int v2)//v1,v2的权重
{
if(v1!=-1&&v2!=-1)
return G.Edge[v1][v2];
else
return 0;
}
int FirstNeighbor(Graph G,int v)//返回v的第一个邻接顶点
{
if(v!=-1)
{
for(int col=0;col<G.numVetr;col++)
if(G.Edge[v][col]>0&&G.Edge[v][col]<maxWeight)
return col;
return -1;
}
else
return -1;
}
int NextNeighbor(Graph G,int v,int w)//返回v的邻接顶点w的下一个邻接顶点
{
if(v!=-1&&w!=-1)
{
for(int col=w+1;col<G.numVetr;col++)
if(G.Edge[v][col]>0&&G.Edge[v][col]<maxWeight)
return col;
return -1;
}
else
return -1;
}
void CreateGraph(Graph&G,int n,int m)//建立n个顶点,m条边的带权无向图
{
int i,j,k;
VType e1,e2;
WType weight;
G.numVetr=n;
G.numEdges=m;
cout<<"请输入顶点的数据元素:"<<endl;
for(i=0;i<n;i++)
{
cin>>e1;
G.VertList[i]=e1;
}
i=0;
cout<<"请输入对应顶点和其边的权值:"<<endl;
while(i<m)
{
cin>>e1>>e2>>weight;
j=GetVertPos(G,e1);
k=GetVertPos(G,e2);
if(j!=-1&&k!=-1)
{
G.Edge[j][k]=G.Edge[k][j]=weight;
i++;
}
else
cout<<"边两端信息有误,重新输入!"<<endl;
}
}
//main.cpp
#include"graph.h"
#include<float.h>
#define MAX_TREE_SIZE 100
#define maxValue FLT_MAX
struct EdgeNode{
int tail,head;
WType key;
bool operator<(const EdgeNode& b) const
{
return key>b.key;
}
};
struct MinTree{
EdgeNode *edgeArray;
int maxSize,n;
};
void InitMinTree(MinTree &T)
{
T.edgeArray=new EdgeNode[maxVert];
if(T.edgeArray==NULL)
{cerr<<"存储分配失败!"<<endl;exit(1);}
T.maxSize=maxVert;
T.n=0;
}
void Kruskal(Graph&G,MinTree &T)
{
EdgeNode ed;
int u,v,count;
int n=G.numVetr;
int m=G.numEdges;
priority_queue<EdgeNode>H;//优先队列(最小堆)
for(u=0;u<G.numVetr;u++)
{
v=FirstNeighbor(G,u); //找顶点u的第一个邻接顶点
while(v!=-1)
{
ed.tail=u;
ed.head=v;
ed.key=GetWeight(G,u,v);
H.push(ed); //插入堆
v=NextNeighbor(G,u,v); //取u排在v后面的结点
}
}
int vset[maxVert],sn1,sn2; //vset【】用来判定两个顶点是否连通
for(int i=0;i<G.numVetr;i++)
vset[i]=i; //初始化
count=1; //表示当前构造生成树的第几条边
while(count<G.numVetr)
{
ed=H.top();
H.pop();
u=ed.tail;
v=ed.head;
sn1=vset[v];
sn2=vset[u]; //分别得到两个顶点所属集合编号
if(sn1!=sn2)
{
cout<<"("<<G.VertList[u]<<","<<G.VertList[v]<<","<<ed.key<<")"<<endl;
T.edgeArray[++T.n]=ed;
count++;
for(i=0;i<G.numVetr;i++)
if(vset[i]==sn2)
vset[i]=sn1; //把原来等于sn2的顶点全部划到sn1所对应的几何
}
}
}
void main()
{
Graph G;
int n,m;
cout<<"请输入图的顶点个数:";
cin>>n;
cout<<"请输入图的边数:";
cin>>m;
InitGraph(G);
CreateGraph(G,n,m);
MinTree T; //T中存放最小生成树每条边所对应的顶点和权值
InitMinTree(T);
Kruskal(G,T);
}
/*
4
4
A B C D
A B 1
B C 2
C D 3
A D 4
*/
/*
8
12
A B C D E F G H
A C 10
A H 12
C G 6
H G 4
C D 7
A B 9
H E 2
F G 3
B E 11
B D 8
E F 1
D F 5
*/