Kruskal 最小生成树算法

kruskal.h

kruskal.cpp

#pragma once

#include 
<iostream>
#include 
<vector>
#include 
<algorithm>
#include 
<functional>
#include 
<set>


template
<class Vertex_Type, class Edge_Type>
class Kruskal
{
 typedef Kruskal
<Vertex_Type,Edge_Type>  Self_Type ;
protected:
 
struct Edge_t
 
{
  typedef typename Self_Type::Edge_t  Self_Type ;
  Vertex_Type v1,  v2 ;
  Edge_Type e ;
  Edge_t()
{}
  Edge_t(Vertex_Type 
& _v1,Vertex_Type & _v2,Edge_Type & _e) :
  v1(_v1),v2(_v2),e(_e)
  
{}
  Edge_t(
const Edge_t & edge):v1(edge.v1),v2(edge.v2),e(edge.e)
  
{}
  Edge_t 
& operator=(const Edge_t & edge){ v1=edge.v1,v2=edge.v2,e=edge.e ;return *this ; }
  
bool operator<(const Self_Type & other )const {   return e<other.e ;   }
  
//friend istream &  operator>>(istream & in, Self_Type & edge)
  
//{ in>>edge.v1>>edge.v2>>edge.e ;   return in ;  }
 }
;

 
//
 struct Vertex_t
 
{
  Vertex_Type v ;
  Vertex_t 
* root ;
  Vertex_t()
{}
  Vertex_t(Vertex_Type 
& _v, Vertex_t * _r=0): v(_v),root(_r){}
  
bool operator<(const Vertex_t & other ) const {  return v<other.v ;   }
  
bool isRoot(voidconst    {  return 0==root || root==this;    }
  
bool isSingle(voidconst   {  return 0==root ;          }
 }
;
 
//
 std::vector<Edge_t> Edges ;
 std::vector
<Edge_t> resultEdges ;
 size_t edgeNum ;
 size_t vertexNum ;
 std::
set<Vertex_t> VexSet ;

public:
 Kruskal():edgeNum(
0),vertexNum(0){}
 Kruskal(size_t vNum, size_t eNum): Edges(eNum),edgeNum(eNum),vertexNum(vNum)
{}
 Kruskal(size_t vNum, size_t eNum, Edge_t 
& default):Edges(eNum,default),edgeNum(eNum),vertexNum(vNum){}
 
virtual ~Kruskal() {}
 
void setNum( size_t vNum, size_t eNum) {   edgeNum=eNum,vertexNum=vNum ;   }
 
virtual void sort(void)
 
{
  std::sort(Edges.begin(),Edges.end()) ;
 }

 
virtual void input(std::istream & in)
 
{
  
if(Edges.size()<edgeNum)
   Edges.resize(edgeNum) ;
  
for(size_t i=0; i<edgeNum; ++i)
  
{
   
in>>Edges[i].v1>>Edges[i].v2>>Edges[i].e; // you may change this
   VexSet.insert(Edges[i].v1) ;
   VexSet.insert(Edges[i].v2);
  }

 }

 friend std::istream 
&  operator>>(std::istream & in, Self_Type & objectobject.input(in) ;  return in ; }
 
 friend std::ostream 
&  operator<<(std::ostream & out, Self_Type & object)
 
{
  
out<<"vertex_1   vertex_2   edge  " ;
  std::vector
<Edge_t>  & edges=object.resultEdges ;
  
for(size_t i =0; i<edges.size() ; ++i)
   
out<<edges[i].v1<<" "<<edges[i].v2<<" "<<edges[i].e<<std::endl ;
  
return out ;
 }


 

 Vertex_t 
& findRoot(Vertex_t & v )
 
{
  
if (v.isRoot())
   
return v ;
  
return findRoot(*v.root) ;
 }


 
virtual bool isInSameSet(Vertex_Type & _v1, Vertex_Type & _v2)
 
{
  Vertex_t 
&  v1=findRoot(*VexSet.find(_v1)) ;
  Vertex_t 
&  v2=findRoot(*VexSet.find(_v2)) ;

  
if(v1.v==v2.v)
   
return true ;
  
if(v1.isSingle())
   v1.root
=&v2 ;
  
else
   v2.root
=&v1 ;

  
return false;
 }

 
void run(void)
 
{
  sort() ;
  
for(size_t i=0; i<edgeNum; ++i)
  
{
   Vertex_Type 
& v1=Edges[i].v1 ;
   Vertex_Type 
& v2=Edges[i].v2 ;
   
if! isInSameSet(v1,v2) )
    resultEdges.push_back( Edges[i] );
  }

 }

}
;

 


#include 
"kruskal.h"
#include 
<fstream>
#include 
<iostream>
#include 
<vector>
#include 
<algorithm>
#include 
<functional>
#include 
<set>
#include 
<string>

using namespace std ;

struct edg_t 
{
 
int vec1,vec2, weight ;
 friend istream 
&  operator>>(istream & in, edg_t & edg)
 
{
  
in>>edg.vec1>>edg.vec2>>edg.weight ;
  
return in ;
 }

}
;

bool cmp(const edg_t & left, const edg_t & right )
{
 
return left.weight<right.weight ;
}


void kruskal(fstream & fin) ;
size_t findRoot(vector
<int> & vec, int index) ;

template
<class vetex_type, class edge_type>
void test(istream &  fin)
{
 
int vecNum, edgNum ;
 fin
>>vecNum>>edgNum ;
 
{
  Kruskal
<vetex_type,edge_type> sun(vecNum, edgNum) ;
  fin
>>sun ;
  sun.run() ;
  cout
<<sun ;
 }
 
 getchar() ;
}


int _tmain(int argc, _TCHAR* argv[])
{
 fstream fin(
"data.txt",ios::in) ;
 test
<string,int>(fin) ;
 test
<char,int>(fin) ;
 test
<int,int>(fin) ;

 cout
<<"  ---------------   " ;

 kruskal(fin) ;
 getchar() ;
 fin.close() ;
 
return 0;
}


// find the root of the set with the vec[index] in it
size_t findRoot(vector<int> & vec, int index)
{
 
if(index>=vec.size())
  
return 0 ;
 
if( vec[index]==-1// is it a root ?
  return index ;
 
return findRoot(vec,vec[index]) ;
}

//
void kruskal(fstream & fin)
{
 
if(!fin)
  cout
<<"Error in open file! ";
 
//cout<<fin.rdbuf() ;
 int VecNum, EdgNum ;
 fin
>>VecNum>>EdgNum ;
 vector
<edg_t>  edgVec(EdgNum) ;
 vector
<int> resultVec(VecNum,-1) ;
 
for(int i=0; i<EdgNum; i++)
  fin
>>edgVec[i] ;

 
//step 1 : sort by edge
 sort(edgVec.begin(), edgVec.end(), ptr_fun(cmp));

 
// step 2: for each edge in the sorted @edgVec, 
 
// select it's two vertex if they are not in the same set and union the two set
 for(int i=0; i<EdgNum; i++)
 
{
  edg_t 
&  edg=edgVec[i] ;

  
// find the two set of each vertex of the edge
  size_t lRoot=findRoot(resultVec,edg.vec1-1);
  size_t rRoot
=findRoot(resultVec,edg.vec2-1);
  
if(lRoot==rRoot) // are they in the same set ?
   continue ;
  
// here we union the two set
  if(-1==resultVec[lRoot])
   resultVec[lRoot]
=rRoot ;
  
else
   resultVec[rRoot]
=lRoot ;

  cout
<<edg.vec1<<" "<<edg.vec2<<" "<<edg.weight
   
<<endl ; // print the result
 }

}

 

 

data.txt

9 14
sda erb 4
sda gggh 8
erb itc 8
erb gggh 11
itc qwed 7
itc xcvf 4
itc asdfi 2
qwed erte 9
qwed xcvf 14
erte xcvf 10
xcvf dfgg 2
dfgg gggh 1
dfgg asdfi 6
gggh asdfi 7

9 14
a b 4
a h 8
b c 8
b h 11
c d 7
c f 4
c i 2
d e 9
d f 14
e f 10
f g 2
g h 1
g i 6
h i 7

9 14
1 2 4
1 8 8
2 3 8
2 8 11
3 4 7
3 6 4
3 9 2
4 5 9
4 6 14
5 6 10
6 7 2
7 8 1
7 9 6
8 9 7

9 14
1 2 4
1 8 8
2 3 8
2 8 11
3 4 7
3 6 4
3 9 2
4 5 9
4 6 14
5 6 10
6 7 2
7 8 1
7 9 6
8 9 7

原文地址:https://www.cnblogs.com/sunkang/p/2038833.html