zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    概率论与数理统计(3)
    平衡二叉树(AVL)实现(3)删除
    平衡二叉树(AVL)实现(1)
    利用C#2005实现数据表的基本操作
    用js计算时间差,得到比较人性化的结果
    WinForm 窗口最小化到托盘 notifyIcon
    wget 使用技巧
    使用javascript从url获取参数值
    OWC做电子表格和图表的试验
    C#中combobox 和TreeView控件属性、事件、方法收集
  • 原文地址:https://www.cnblogs.com/sunkang/p/2038833.html
Copyright © 2011-2022 走看看