最小生成树的Prim算法

来源:互联网 发布:asp.net和php对比 编辑:程序博客网 时间:2024/06/05 05:10
//  gramtx-minspantree.h#pragma once#include<iostream>#include<malloc.h>#include<stdlib.h>#include<assert.h>using namespace std;#define DEFAULT_VERTICES_SIZE  10//#define T char//#define E int  //权值类型#define MAX_COST  0X7FFFFFtemplate< class T,class E>class GraphMtx{public:  GraphMtx( int sz=DEFAULT_VERTICES_SIZE)  //初始化图  {  MaxVertices=sz>DEFAULT_VERTICES_SIZE ? sz : DEFAULT_VERTICES_SIZE;  VerticesList=new T[MaxVertices];   for(int i=0;i<MaxVertices;++i)   {    VerticesList[i]='#';   }   Edge=new E*[MaxVertices];  //开辟数组空间   for(int i=0;i<MaxVertices;++i)   {    Edge[i]=new E[MaxVertices];   }   for(int i=0;i<MaxVertices;++i)   {    for(int j=0;j<MaxVertices;++j)    {     if(i==j)     {      Edge[i][j]=0;     }     else     {     Edge[i][j]=MAX_COST;     }    }   }   numVertices=numEdges=0; //初始化一个空图  }public: bool InsertVertex(T v)  //插入顶点 {  if(numVertices>=MaxVertices)   return false;  VerticesList[numVertices++]=v;  return true;    } bool InsertEdge(T vertex1,T vertex2,E cost )  //插入边 {  int v1=getPosVertex(vertex1);     int v2=getPosVertex(vertex2);  if(v1==-1||v2==-1)   return false;  Edge[v1][v2]=Edge[v2][v1]=cost;  //给相应的边附上相应的权值  numEdges++;    //边的个数增加  return true; } void ShowGraph()const //显示 {  cout<<"  ";  for(int i=0;i<numVertices;++i)   cout<<VerticesList[i]<<" ";  cout<<endl;  for(int i=0;i<numVertices;++i)  {   cout<<VerticesList[i]<<" ";   for(int j=0;j<numVertices;++j)   {    if(Edge[i][j]==MAX_COST)    {     cout<<"@"<<" ";    }    else    {    cout<<Edge[i][j]<<" ";    }   }    cout<<endl;  }     } int getPosVertex(T vertex)const  //获取顶点所在位置 {  for(int i=0;i<numVertices;++i)  {   if(VerticesList[i]==vertex)    return i;  }  return -1;    }public: int GetWeight(const int v1,const int v2)  //获得权值 {  if(v1!=-1&&v2!=-1)   return Edge[v1][v2];  else   return MAX_COST; } /* Kruskal算法--从边的方面考虑构建一颗MST: 先找到一条权值最小的边,再选择另外一条权值最小的边, 但是前提是不能构成环形结构,即这两条边不连通。 */public: typedef struct Edge {  int begin;  int end;  E cost; }Edges; void  MinSpanTree_Kruskal( ) {  int n=numVertices;  int i,j;  Edges *edge=new Edges[n*(n-1)/2];  assert(edge!=NULL);  int k=0;  for( i=0;i<n;i++)  {   for( j=i;j<n;j++)   {    if(Edge[i][j] !=  0 && Edge[i][j] != MAX_COST) //说明边存在                {    edge[k].begin=i;    edge[k].end=j;    edge[k].cost=Edge[i][j];//即A到B有一条权值为6的边    k++; //记录边的个数    }   }  }  for(i=0;i<k;i++)  //对边的权值大小进行排序  {   for(j=i+1;j<k;j++)   {    if(edge[i].cost>edge[j].cost)    {     swap(edge[i],edge[j]);    }   }  }  for( i=0;i<k;i++)  {   cout<<VerticesList[edge[i].begin]<<"-->"<<VerticesList[edge[i].end]<<" "<<edge[i].cost;   cout<<endl;  }   cout<<"--------------------"<<endl;  int *father=new int[n];  assert(father!=NULL);  for( i=0;i<n;i++)  {   father[i]=i; //自己的父节点就是自己  }  for(i=0;i<n;i++)  {   if(!Is_same(father,edge[i].begin,edge[i].end)) //判断是否属于同一个集合   {    cout<<VerticesList[edge[i].begin]<<"-->"<<VerticesList[edge[i].end]<<" "<<edge[i].cost;    cout<<endl;    Mark_same(father,edge[i].begin,edge[i].end);   }  } } bool Is_same(int *father,int i,int j) {  while(father[i]!=i)   {   i=father[i];  }  while(father[j]!=j)  {   j=father[j];  }  return i==j;  //不相同则说明不是同一个集合 } void Mark_same(int *father,int i,int j) {  while(father[i]!=i)  {   i=father[i];  }  while(father[j]!=j)  {   j=father[j];  }  father[j]=i; }public: int NumberOfVertex()const  //返回当前顶点的个数 {  return numVertices; } int NumberOfEdge()const     //返回当前边数 {  return numEdges; } private: int MaxVertices; //最大顶点个数 int numVertices;  //当前顶点个数 int numEdges;   //当前边的个数 T *VerticesList;  //顶点的存储空间    E **Edge;   //边的存储空间};// test,cpp#include"gramtx-minspantree.h"void main(){ GraphMtx<char,int>gm; gm.InsertVertex ('A'); gm.InsertVertex ('B'); gm.InsertVertex ('C'); gm.InsertVertex ('D'); gm.InsertVertex ('E'); gm.InsertVertex ('F'); gm.InsertEdge ('A','B',6); gm.InsertEdge ('A','C',1); gm.InsertEdge ('A','D',5); gm.InsertEdge ('B','C',5); gm.InsertEdge ('B','E',3); gm.InsertEdge ('C','D',5); gm.InsertEdge ('C','E',6); gm.InsertEdge ('C','F',4); gm.InsertEdge ('D','F',2); gm.InsertEdge ('E','F',6); gm.ShowGraph ();gm.MinSpanTree_Kruskal ();}
原创粉丝点击