// krusal
算法根据
MST
性质。若点集合
U ~
点集合
V
存在一点最短路径
s~t,
则最小生成树必包含
s~t
这条路。
//
利用反证法(或者剪贴法)可以证明
// krusal
算法是将整个图每个顶点看成一个集合。主要是合并集合,直到只剩一个集合为止
//
同时考虑以边为对象的
有向图
// 用最小边去找集合
#include
"stdafx.h"
#include
#include
#include
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<
//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
;
}