Krusal算法 方法2

// krusal 算法根据 MST 性质。若点集合U ~点集合 V 存在一点最短路径s~t, 则最小生成树必包含 s~t 这条路。
// 利用反证法(或者剪贴法)可以证明

// krusal 算法是将整个图每个顶点看成一个集合。主要是合并集合,直到只剩一个集合为止

// 同时考虑以边为对象的 有向图



// 用最小边去找集合
#include "stdafx.h"
#include <iostream>
#include <vector>
#include <list>
#include <algorithm>

enum
{
      Vertex_No_Connection     = -1,
      Vertex_Total_Number     = 5,
      Vertex_Max_Edge_Value    = 10000,
};


int arrayPathScheme [ Vertex_Total_Number][ Vertex_Total_Number ] =
{
     0,   10,   -1,  30,  100,
     -1,   0,   50,  -1,   -1,
     -1,  -1,   0,   -1,   10,
     -1,  -1,   20,   0,   60,
     -1,  -1,   -1,  -1,    0,
};

// 集合
struct SVertexSet
{
      int idSet ;
      std::list <int> listVertex;
};

std ::list< SVertexSet*> listVertexSet ;

// 三元表
struct SEdgeInfoNode
{
      int nEdgeValue ;
      int nSourceVertex ;
      int nEndVertex ;
};

// 三元表 并且递增
std ::list< SEdgeInfoNode*> listEdgeInfoSet ;

bool SortByCmp( SEdgeInfoNode* &pPre , SEdgeInfoNode* &pNext )
{
      if( pPre ->nEdgeValue < pNext->nEdgeValue )
           return true ;

      return false ;
}

void PrintAll()
{
      std::list <SEdgeInfoNode*>:: iterator iBegin = listEdgeInfoSet .begin();
      std::list <SEdgeInfoNode*>:: iterator iEnd    = listEdgeInfoSet .end();
      for( ; iBegin != iEnd; ++ iBegin )
     {
           SEdgeInfoNode* pEdgeInfo = (*iBegin);
           if( pEdgeInfo )
          {
               std::cout <<" Source->"<< pEdgeInfo->nSourceVertex <<" Dest->"<< pEdgeInfo->nEndVertex <<"   Vlaue:"<< pEdgeInfo->nEdgeValue <<std:: endl;
          }
     }
}

void arrayInit()
{
      // 数组预处理处理回环的值 i -> j = 50  同时 j -> i = 30.
      // 注销回环。则将i -> j = 50 改为i -> j = -1.
      for( int i = 0; i < Vertex_Total_Number - 1; ++i )
     {
           for( int j = i + 1; j < Vertex_Total_Number; ++ j )
          {
               if( arrayPathScheme [i][ j] > 0 && arrayPathScheme [j][ i] > 0 )
              {
                    if( arrayPathScheme [i][ j] < arrayPathScheme [j][ i] )
                         arrayPathScheme[j ][i] = -1;
                    else
                         arrayPathScheme[i ][j] = -1;
              }
          }
     }

      // 初始化顶点集合
      listVertexSet.clear ();
      for( int i = 0; i < Vertex_Total_Number ; ++i )
     {
           SVertexSet* pVertexNode = new SVertexSet;
           if( !pVertexNode )
          {
               std::cout <<"Error 2"<< std::endl ;
               system("pause" );
               return ;
          }

           pVertexNode->idSet = i;
           pVertexNode->listVertex .push_back( i );
          
           listVertexSet.push_back ( pVertexNode );
     }

      // 初始化三元表
      listEdgeInfoSet.clear ();
      for( int i = 0; i < Vertex_Total_Number ; ++i )
     {
           for( int j = 0; j < Vertex_Total_Number ; ++j )
          {
               int nEdgeValue = arrayPathScheme[ i][j ];
               if( 0 == nEdgeValue || -1 == nEdgeValue )
                    continue;

               SEdgeInfoNode* pEdgeInfoNode = new SEdgeInfoNode ;
               if( !pEdgeInfoNode )
              {
                    std::cout <<"Error 3"<< std::endl ;
                    system("pause" );
                    return ;
              }

               pEdgeInfoNode->nEdgeValue      = nEdgeValue;
               pEdgeInfoNode->nSourceVertex   = i;
               pEdgeInfoNode->nEndVertex      = j;

               listEdgeInfoSet.push_back ( pEdgeInfoNode );
          }
     }

      //PrintAll();
      listEdgeInfoSet.sort ( SortByCmp );
      //std::cout<<std::endl<<std::endl;
      //PrintAll();
}

bool IsInTheSameSet( int nSourceIndex , int nDestIndex, SVertexSet * &pSourceSet, SVertexSet* &pDestSet );

int _tmain( int argc , _TCHAR* argv[])
{
      arrayInit();

      int nSelectedEdge = 0;   // 当边取出为 Vertex_Total_Num - 1 条时,则最小生成树构建完成
      std::list <SEdgeInfoNode*>:: iterator listEdgeBegin = listEdgeInfoSet .begin();
      std::list <SEdgeInfoNode*>:: iterator listEdgeEnd    = listEdgeInfoSet .end();
      for( ; listEdgeBegin != listEdgeEnd; ++ listEdgeBegin )
     {
           SEdgeInfoNode* pEdgeInfoNode = (*listEdgeBegin);
           if( !pEdgeInfoNode )
          {
               std::cout <<"Error 4"<< std::endl ;
               system("pause" );
               return 0;
          }

           int  nSourceIndex = pEdgeInfoNode ->nSourceVertex;
           int  nDestIndex    = pEdgeInfoNode-> nEndVertex;
           SVertexSet* pSourceSet = NULL;
           SVertexSet* pDestSet    = NULL;
          
           bool bIsInTwoSet = IsInTheSameSet( nSourceIndex, nDestIndex , pSourceSet, pDestSet );
           if( true == bIsInTwoSet )
          {
               // 在同一集合内 则不处理,取下一条边
               continue;
          }
           else  
          {
               // 在不同的集合内
               // pSourceSet 合并到 pDest 集合中
               if( !pSourceSet ||  !pDestSet )
              {
                    std::cout <<"Error 5"<< std::endl ;
                    system("pause" );
                    return 0;
              }

               std::copy ( pSourceSet-> listVertex.begin (), pSourceSet ->listVertex. end(), pDestSet ->listVertex. begin() );
               std::list <SVertexSet*>:: iterator ilistFind = listVertexSet .begin();
               std::list <SVertexSet*>:: iterator ilistEnd   = listVertexSet .end();
               for( ; ilistFind != ilistEnd; ++ ilistFind )
              {
                    if( (*ilistFind ) && (*ilistFind) == pDestSet )
                         break;
              }
               if( ilistFind != listVertexSet. end() )
                    listVertexSet.erase ( ilistFind );

               delete pDestSet ;

              ++ nSelectedEdge;
               // 输出
               std::cout <<" SourceNode-> "<< pEdgeInfoNode->nSourceVertex <<"  DestNode->"<< pEdgeInfoNode->nEndVertex <<"  NodeValue:"<< pEdgeInfoNode->nEdgeValue <<std:: endl;

               if( Vertex_Total_Number - 1 == nSelectedEdge )
                    break;
          }
     }

      system( "pause" );
      return 0;
}

bool IsInTheSameSet( int nSourceIndex , int nDestIndex, SVertexSet * &pSourceSet, SVertexSet* &pDestSet )
{
      int idSetSource = -1, idSetDest = -1;
      std::list <SVertexSet*>:: iterator ilistVertexBegin = listVertexSet .begin();
      std::list <SVertexSet*>:: iterator ilistVertexEnd    = listVertexSet .end();
      for( ; ilistVertexBegin != ilistVertexEnd; ++ilistVertexBegin )
     {
           SVertexSet* pNowVertex = (*ilistVertexBegin);
           if( !pNowVertex )
          {
               std::cout <<"Error 6"<< std::endl ;
               system("pause" );
               return 0;
          }

           std::list <int>:: iterator ilistIntBegin  pNowVertex ->listVertex. begin();
           std::list <int>:: iterator ilistIntEnd    =  pNowVertex ->listVertex. end();
           for( ; ilistIntBegin != ilistIntEnd; ++ilistIntBegin )
          {
               if( (*ilistIntBegin ) == nSourceIndex )
              {    
                    idSetSource  pNowVertex ->idSet;
                    pSourceSet  =  pNowVertex ;
              }

               if( (*ilistIntBegin ) == nDestIndex )
              {
                    idSetDest  =  pNowVertex ->idSet;
                    pDestSet   =  pNowVertex;
              }
          }


           if( idSetDest != -1 && idSetSource != -1 )
               break;
     }

      if( idSetSource != -1 && idSetSource == idSetDest )
           return true ;

      return false ;
}



  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值