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