最小生成树--Kruskal算法

//  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 ();
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值