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

  • 相关阅读:
    target runtime apache v6.0 not defined解决
    java.lang.AbstractMethodError: javax.servlet.jsp.JspFactory.getJspApplicationContext(Ljavax/servlet/ServletContext;)Ljavax/servlet/jsp/JspApplicationContext;
    The valid characters are defined in RFC 7230 and RFC 3986问题
    invalid END header解决方法
    You have more than one version of ‘org.apache.commons.logging.Log’ visible, which is not allowed问题解决
    Invalid character found in the request target. The valid characters are defined in RFC 7230 and RFC 3986
    在eclipse中import java web项目时遇到的一些问题并将该项目通过tomcat发布
    java byte转string 涉及到字节流中有中文
    spring+mybatis框架搭建时遇到Mapped Statements collection does not contain value for...的错误
    试试看读一下Zepto源码
  • 原文地址:https://www.cnblogs.com/sunkang/p/2038833.html
Copyright © 2011-2022 走看看