最小生成树

//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

*/

 

posted @ 2012-11-22 22:56  ♂咱說 ろ算  阅读(225)  评论(0编辑  收藏  举报