Krusal算法 方法一

来源:互联网 发布:java 为什么没有二叉树 编辑:程序博客网 时间:2024/06/04 19:31
// krusal 算法根据 MST 性质。若点集合U ~点集合 V 存在一点最短路径s~t, 则最小生成树必包含 s~t 这条路。
// 利用反证法(或者剪贴法)可以证明

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

// 这里主要以集合为考虑对象 有向图


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

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

      Vertex_No_In_Set       = 0,
      Vertex_In_Set          = 1,
};

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,
};


// 顶点 V0 ~ 其他顶点的排序
// 顶点 V1 ~ 其他顶点的排序
// V2 V3 V4
std ::list< int> listVertexEdgeSortSet [Vertex_Total_Number];

struct SVertexSet
{
      int idVertexSet  // 集合 ID  每个ID 为唯一值,唯一标识这个集合
      std::vector <int> vecVetexSet;           // 当前顶点的集合
      int nSourceVertex ;                      // 在该集合内
      int nMinEdgeToOtherSet ;    
      int nDestVertex ;
      SVertexSet* pNextDestVetex ;

      SVertexSet( int nVertexIndex )
     {
           pNextDestVetex = NULL ;
           nSourceVertex = nVertexIndex ;
           idVertexSet   = nVertexIndex ;
           nDestVertex = Vertex_No_Connection ;
           vecVetexSet.push_back ( nVertexIndex );

           nMinEdgeToOtherSet = Vertex_Max_Edge_Value ;

           if( !listVertexEdgeSortSet [nVertexIndex]. empty() )
          {
               int nDestIndex = listVertexEdgeSortSet [nVertexIndex]. back();
               nDestVertex = nDestIndex ;
               nMinEdgeToOtherSet = arrayPathScheme [nVertexIndex][ nDestVertex];
          }
     }
};

std ::list< SVertexSet*> listVertexSet ;

 
// 数组预处理处理回环的值 i -> j = 50  同时 j -> i = 30.
// 注销回环。则将 i -> j = 50 改为i -> j = -1.
void arrayInit()
{
      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;
              }
          }
     }
}

void arrayListSortInit()
{
      for( int i = 0; i < Vertex_Total_Number ; ++i )
           listVertexEdgeSortSet [i]. 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( nEdgeValue == 0 || nEdgeValue == -1 )
                    continue;

               std::list <int>:: iterator iListBegin = listVertexEdgeSortSet [i]. begin();
               std::list <int>:: iterator iListEnd    = listVertexEdgeSortSet [i]. end();
               for( ; iListBegin != iListEnd; ++ iListBegin )
              {
                    if( arrayPathScheme [i][(* iListBegin)] <nEdgeValue )
                         break;
              }

               listVertexEdgeSortSet [i]. insert( iListBegin , j );
          }
     }
}

void Init()
{

      for( int i = 0; i < Vertex_Total_Number ; ++i )
     {
           SVertexSet* pNewVertex = new SVertexSet(i );
           if( !pNewVertex )
          {
               return ;
          }

           listVertexSet.push_back ( pNewVertex );
     }
}

void InitNextVertex()
{
      std::list <SVertexSet*>:: iterator iBegin = listVertexSet .begin();
      std::list <SVertexSet*>:: iterator iFind   = listVertexSet .begin();
      std::list <SVertexSet*>:: iterator iEnd    = listVertexSet .end();
      std::list <SVertexSet*>:: iterator iNext ;
      for( ; iFind != iEnd; ++ iFind )
     {
           SVertexSet* pVertex = (*iFind);
           if( pVertex && Vertex_No_Connection != pVertex ->nDestVertex )
          {
               int nIndexAdd = pVertex-> nDestVertex;
               iNext = iBegin ;
               for( int i = 1; i <= nIndexAdd ; ++i )
                   ++ iNext;

               pVertex->pNextDestVetex = (*iNext);
          }
     }
}

SVertexSet * FindVertexSetFromId( int nVertexId , int idSource , int idDest )
{
      std::list <SVertexSet*>:: iterator iBegin = listVertexSet .begin();
      std::list <SVertexSet*>:: iterator iEnd    = listVertexSet .end();
      for( ; iBegin != iEnd; ++ iBegin )
     {
           SVertexSet* pVertex = (*iBegin);
           if( !pVertex )
               return NULL ;

           if( pVertex ->idVertexSet == idSource || pVertex ->idVertexSet == idDest )
               continue;

           std::vector <int>:: iterator iVecBegin = pVertex ->vecVetexSet. begin();
           std::vector <int>:: iterator iVecEnd    = pVertex ->vecVetexSet. end();
           for( ; iVecBegin != iVecEnd; ++ iVecBegin )
          {
               if( (*iVecBegin ) == nVertexId )
                    return pVertex ;
          }
     }

      return NULL ;
}

void CombineSet( SVertexSet* pFindMinEdge , SVertexSet* pDestMinEdgeVertex )
{
      if( !pDestMinEdgeVertex || !pFindMinEdge )
     {
           std::cout <<"异常 "<<std ::endl;
           return ;
     }

      // 消除原先集合的最小值
      int nSourceVertex     = pFindMinEdge->nSourceVertex ;
      int nDest = listVertexEdgeSortSet [nSourceVertex]. back();
      listVertexEdgeSortSet [nSourceVertex]. pop_back();

      // 重新找当前集合的最小值
      int nCurrentMinValue = pFindMinEdge ->nMinEdgeToOtherSet;
      int nDestMinValue     = pDestMinEdgeVertex ->nMinEdgeToOtherSet;

      if( nDestMinValue <= nCurrentMinValue )
     {
           pFindMinEdge->nSourceVertex   = pDestMinEdgeVertex ->nSourceVertex;
           pFindMinEdge->nMinEdgeToOtherSet = pDestMinEdgeVertex ->nMinEdgeToOtherSet;
           pFindMinEdge->nDestVertex     = pDestMinEdgeVertex ->nDestVertex;
           pFindMinEdge->pNextDestVetex = pDestMinEdgeVertex ->pNextDestVetex;
     }
      else
     {

           // 求出当前pFindMinEdge 中的最小值
           int nMinEdgeValue = Vertex_Max_Edge_Value;
           int nSourceIndex   = -1;
           int nDestVertexIndex ;
           std::vector <int>:: iterator iVecBegin = pFindMinEdge ->vecVetexSet. begin();
           std::vector <int>:: iterator iVecEnd    = pFindMinEdge ->vecVetexSet. end();
           for( ; iVecBegin != iVecEnd; ++ iVecBegin )
          {
               int nVertexIndex = (*iVecBegin);

               if( listVertexEdgeSortSet [nVertexIndex]. empty() )
                    continue;

               int nDestIndex = listVertexEdgeSortSet [nVertexIndex]. back();
               if( arrayPathScheme [nVertexIndex][ nDestIndex] < nMinEdgeValue )
              {
                    nMinEdgeValue      = arrayPathScheme [nVertexIndex][ nDestIndex];
                    nSourceIndex       = nVertexIndex;
                    nDestVertexIndex   = nDestIndex ;
              }
          }


           if( nSourceIndex == -1 || nDestMinValue <= nMinEdgeValue )
          {
               pFindMinEdge->nSourceVertex       = pDestMinEdgeVertex ->nSourceVertex;
               pFindMinEdge->nMinEdgeToOtherSet = pDestMinEdgeVertex ->nMinEdgeToOtherSet;
               pFindMinEdge->nDestVertex         = pDestMinEdgeVertex ->nDestVertex;
               pFindMinEdge->pNextDestVetex      = pDestMinEdgeVertex ->pNextDestVetex;
          }
           else
          {
               pFindMinEdge->nSourceVertex       = nSourceIndex ;
               pFindMinEdge->nDestVertex         = nDestVertexIndex ;
               pFindMinEdge->nMinEdgeToOtherSet = nMinEdgeValue ;
               // 找到另一个点所属的集合
               int idSourceSet = pFindMinEdge ->idVertexSet;
               int idDestSet    = pDestMinEdgeVertex ->idVertexSet;
               pFindMinEdge->pNextDestVetex      = FindVertexSetFromId ( nDestVertexIndex, idSourceSet, idDestSet );
          }
     }

      std::copy ( pFindMinEdge-> vecVetexSet.begin (), pFindMinEdge ->vecVetexSet. end(),
                  pDestMinEdgeVertex ->vecVetexSet. begin() );
}

int _tmain( int argc , _TCHAR* argv[])
{
      arrayInit();
      arrayListSortInit();
      Init();
      InitNextVertex();
      // n-1 条边
      for( int nIndex = 0; nIndex < Vertex_Total_Number - 1; ++nIndex )
     {
           int nMinEdge = Vertex_Max_Edge_Value;
           std::list <SVertexSet*>:: iterator iFind   = listVertexSet .end();    // 设置其为空
           std::list <SVertexSet*>:: iterator iBegin = listVertexSet .begin();
           std::list <SVertexSet*>:: iterator iEnd    = listVertexSet .end();
           for( ; iBegin != iEnd; ++ iBegin )
          {
               SVertexSet* pVertexSet = (*iBegin);
               if( pVertexSet ->nDestVertex == Vertex_No_Connection )
                    continue;

               if( pVertexSet ->nMinEdgeToOtherSet < nMinEdge )
              {
                    iFind     = iBegin;
                    nMinEdge  = pVertexSet ->nMinEdgeToOtherSet;
              }
          }

           if( iFind == listVertexSet. end() || !(*iFind ) || nMinEdge == Vertex_Max_Edge_Value )
          {
               std::cout <<"异常 "<<std ::endl;
               system( "pause" );
               return 0;
          }

           SVertexSet* pFindMinEdge = (*iFind);
           SVertexSet* pDestMinEdgeVertex = (*iFind )->pNextDestVetex;
           if( !pFindMinEdge || !pDestMinEdgeVertex )
          {
               std::cout <<"异常 "<<std ::endl;
               system("pause" );
               return 0;
          }

           // 输出最短路径
           std::cout <<" SourceNode:"<< pFindMinEdge->nSourceVertex <<"  DestNode:"<< pFindMinEdge->nDestVertex <<"  EdgeValue: "<< pFindMinEdge->nMinEdgeToOtherSet <<std:: endl;
           // 1. 更新合并后的集合
           CombineSet( pFindMinEdge , pDestMinEdgeVertex );

           // 2. 更新指向pDestMinEdgeVertex 指向pFind
           iBegin = listVertexSet .begin();
           for( ; iBegin != iEnd; ++ iBegin )
          {
               if( (*iBegin ) && (*iBegin)-> pNextDestVetex == pDestMinEdgeVertex )
                   (* iBegin)->pNextDestVetex = pFindMinEdge ;
          }

           // Begin 集合删除
           std::list <SVertexSet*>:: iterator iFindDest = listVertexSet .begin();
           std::list <SVertexSet*>:: iterator iFindEnd   = listVertexSet .end();
           for( ; iFindDest != iFindEnd; ++ iFindDest )
          {
               if( (*iFindDest ) == pDestMinEdgeVertex )
                    break;
          }
               //pDestMinEdgeVertex
           if( pDestMinEdgeVertex )
               delete pDestMinEdgeVertex ;
          
           if( iFindDest != iFindEnd )
               listVertexSet.erase ( iFindDest );
     }
      system( "pause" );
      return 0;
}



0 0