// 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 0X7FFFFF
template< 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 ();
}
最小生成树的Prim算法
最新推荐文章于 2020-11-21 20:29:07 发布