利用邻接矩阵做存储结构——通过克鲁斯卡尔算法构造最小生成树,话不多说,且看代码如下:
#include<iostream>
using namespace std;
//二维数组存储邻接矩阵
//一维数组存储顶点信息
//-----图的邻接矩阵表示----
#define MaxInt 32767 //表示极大值
#define MVNum 100 //最大顶点数
typedef string VerTexType;//假设顶点的数据类型为字符串型
typedef int ArcType; //假设边的权值类型为字符串型
typedef struct
{
VerTexType vexs[MVNum];//顶点表
ArcType arcs[MVNum][MVNum];//邻接矩阵各边之间的权值
int vexnum, arcnum;//图的当前顶点数和边数
}AMGraph;
//采用邻接矩阵表示法创建无向网
//返回顶点在邻接矩阵中对应的下标
int LocateVex(AMGraph& G, char *v1)
{
for (int i = 0; i<G.vexnum; i++)
{
if (v1 == G.vexs[i])
return i;
}
}
void CreateUDN(AMGraph& G)
{
int i, j, k,w;
string v1,v2;
cin >> G.vexnum >> G.arcnum; //输入总顶点数和总边数
for (i = 0; i < G.vexnum; ++i)
cin >> G.vexs[i]; //依次输入点的信息***顶点数组
for (i = 0; i < G.vexnum; ++i)
for (j = 0; j < G.vexnum; ++j)
G.arcs[i][j] = MaxInt; //初始化邻接矩阵,使每个权值初始化为极大值
for (k = 0; k < G.arcnum; ++k) //构造邻接矩阵
{
cin >> v1 >> v2 >> w; //输入一条边依附的顶点及其权值
i = LocateVex(G, &v1[0]); //确定v1和v2在G中的位置,即顶点数组的下标
j = LocateVex(G, &v2[0]);
G.arcs[i][j] = w; //边<v1,v2>的权值置为w
G.arcs[j][i] = G.arcs[i][j]; //置<v1,v2>的对称边<v2,v1>权值为w
}
for (int i = 0; i < G.vexnum; i++)
{
for (int j = 0; j < G.vexnum; j++)
cout << G.arcs[i][j] << "\t";
cout << endl<<endl;
}
}
//————存储边————
struct Edge
{
VerTexType Head;
VerTexType Tail;
ArcType lowcost;
}Edge[MVNum];
//存边数组的初始化——将边的首尾顶点,权,都存到数组里面
void init(AMGraph G,struct Edge *edge)
{
int k=0;
for(int i=0;i<G.vexnum;i++)
for(int j=i;j<G.vexnum;j++)
{
while(G.arcs[i][j]!=MaxInt)
{
edge[k].Head=G.vexs[i];
edge[k].Tail=G.vexs[j];
edge[k].lowcost=G.arcs[i][j];
k++;
break;
}
}
}
void swap(struct Edge *a,struct Edge *b)
{
struct Edge tem;
tem.Head=a->Head;
a->Head=b->Head;
b->Head=tem.Head;
tem.Tail=a->Tail;
a->Tail=b->Tail;
b->Tail=tem.Tail;
tem.lowcost=a->lowcost;
a->lowcost=b->lowcost;
b->lowcost=tem.lowcost;
}
//按照权值从小到大排序,注意:顶点要随着权而变化
void Sort(struct Edge *edge,int n)
{
int begin=0,end=n-1;
while(begin<end)
{
int max=begin;
int min=begin;
//找出最值的下标
for(int i=begin;i<=end;++i)
{
if(edge[i].lowcost>edge[max].lowcost)
max=i;
if(edge[i].lowcost<edge[min].lowcost)
min=i;
}
//最小值放到开头,和开头交换
swap(&edge[min],&edge[begin]);//权值与下标的关系会变化
if(begin==max)
max=min;
//最大值放到末尾
swap(&edge[max],&edge[end]);//会
++begin;
--end;
}
}
//标识各个顶点所属的连通分量
int Vexset[MVNum];
//——克鲁斯卡尔算法——
void Kruskal(AMGraph G)
{
init(G,Edge);
int i,j,v1,v2, vs1,vs2;
Sort(Edge,G.arcnum);//对各条边按照权值大小进行排序
for(i=0;i<G.vexnum;++i)
Vexset[i]=i;//各点连通分量初始化,先初始化为自身的下标
for(i=0;i<G.arcnum;++i)
{
v1=LocateVex(G,&Edge[i].Head[0]);//起始点的下标
v2=LocateVex(G,&Edge[i].Tail[0]);//终点的下标
vs1=Vexset[v1];//连通分量
vs2=Vexset[v2];
if(vs1!=vs2)
{
cout<<Edge[i].Head<<Edge[i].Tail<<endl;
//Vexset[v2]=vs1; //这个想法只适用于连通分量=vs2的点只有一个
for(j=0;j<G.vexnum;++j)
if(Vexset[j]==vs2)
Vexset[j]=vs1;
}
}
}
int main()
{
AMGraph G;
CreateUDN(G);
cout<<"最短路径:"<<endl;
Kruskal(G);
}
输入实例:
6 10
v1 v2 v3 v4 v5 v6
v1 v2 6
v1 v3 1
v1 v4 5
v2 v3 5
v2 v5 3
v3 v5 6
v3 v4 5
v3 v6 4
v4 v6 2
v5 v6 6