給定乙個帶權值的無向圖,要求權值之和最小的生成樹,常用的演算法有kruskal演算法和prim演算法。這兩個演算法其實都是貪心思想的使用,但又能求出最優解。(**借鑑
一.kruskal演算法
kruskal演算法的基本思想:先將所有邊按權值從小到大排序,然後按順序選取每條邊,假如一條邊的兩個端點不在同乙個集合中,就將這兩個端點合併到同乙個集合中;假如兩個端點在同乙個集合中,說明這兩個端點已經連通了,就將當前這條邊捨棄掉;當所有頂點都在同乙個集合時,說明最小生成樹已經形成。(寫**的時候會將所有邊遍歷一遍)
來看乙個例子:
步驟:(1)先根據權值把邊排序:
ad 5
ce 5
df 6
ab 7
be 7
bc 8
ef 8
bd 9
eg 9
fg 11
(2)選擇ad這條邊,將a、d加到同乙個集合1中
選擇ce這條邊,將c、e加到同乙個集合2中(不同於ad的集合)
選擇df這條邊,由於d已經在集合1中,因此將f加入到集合1中,集合變為a、d、f
選擇ab這條邊,同理,集合1變為a、b、d、f
選擇be這條邊,由於b在集合1中,e在集合2中,因此將兩個集合合併,形成乙個新的集合abcdef
由於e、f已經在同一集合中,捨棄掉bc這條邊;同理捨棄掉ef、bd
選擇eg這條邊,此時所有元素都已經在同一集合中,最小生成樹形成
象徵性地捨棄掉fg這條邊
實現**如下:
#include #include二.prim演算法(**還沒理解)#define maxsize 20
using
namespace
std;
struct
edge;
struct
graph;
void creategraph(graph *g)
g->ver[i] = '\0'
; vertexnum = strlen(g->ver);
cout
<< "
輸入相應的鄰接矩陣
"<
for (int i = 0; i < vertexnum; i++)
}}void
printgraph(graph g)
cout
<
cout
<< "
圖的鄰接矩陣為:
"<
for (int i = 0; i < vertexnum; i++)
cout
<
}}int
getvernum(graph g)
intgetedgenum(graph g)
}
return
res;
}edge *createedges(graph g) }}
for (int i = 0; i < edgenum - 1; i++)
}p[i] =minweightedge;
}returnp;}
void
kruskal(graph g)
for (int i = 0; i < vertexnum - 1; i++)
else
if (index[p[j].begin] == -1 && index[p[j].end] >= 0
) }
}else
if (index[p[j].begin] >= 0 && index[p[j].end] == -1
) }
}else}}
break
; }}}
cout
<< "
mst的邊為:
"<
for (int i = 0; i < vertexnum - 1; i++)
cout
<< "
mst的權值為:
"<< weightsum <
}
prim演算法的基本思想:設定兩個存放頂點的集合,第乙個集合初始化為空,第二個集合初始化為乙個包含所有頂點的集合。首先把圖中的任意乙個頂點a放進第乙個集合,然後在第二個集合中找到乙個頂點b,使b到第乙個集合中的任意一點的權值最小,然後把b從第二個集合移到第乙個集合。接著在第二個集合中找到頂點c,使c到a或b的權值比到第二個集合中的其他任何頂點到a或b的權值都要小,然後把c從第二個集合移到第乙個集合中。以此類推,當第二個集合中的頂點全部移到第乙個集合時,最小生成樹產生。
以上面的圖再次作為例子:
設第乙個集合為v,第二個集合為u。
v=, u=
(1)a連線了兩個頂點,b和d,ab權值為7,ad權值為5,選擇權值小的一條邊和相應的頂點d,將d加入集合v中。v=, u=
(2)觀察包含v中的元素a和d的邊,ab權值為7,bd權值為9,de權值為15,df權值為6,將f加入v中。v=, u=
(3)依次將b(ab)、e(be)、c(ce)、g(eg)加入到集合v中。
(4)最小生成樹的邊包括:ad df ab be ce eg,problem solved
實現**如下:
#include #include三.kruskal演算法和prim演算法的適用情況#include
using
namespace
std;
#define maxsize 20
struct
graph;
void creategraph(graph *g)
g->ver[i] = '\0'
; vertexnum = strlen(g->ver);
cout
<< "
輸入相應的鄰接矩陣
"<
for (int i = 0; i < vertexnum; i++)
}}void
printgraph(graph g)
cout
<
cout
<< "
圖的鄰接矩陣為:
"<
for (int i = 0; i < vertexnum; i++)
cout
<
}}int
getvernum(graph g)
//將不鄰接的頂點之間的權值設為
void setweight(graph *g) }}
}void prim(graph g, int *parent)
used[
0] = 1
;
for (int i = 0; i < vertexnum - 1; i++)
}parent[j] =closest[j];
used[j] = 1
;
for (int k = 0; k < vertexnum; k++) }}
}void printmst(graph g, int *parent)
cout
<< "
mst的權值為
"<< weight <
}int
main()
kruskal演算法適用於邊稀疏的情況(要進行排序),prim演算法適用於邊稠密的情況。
Kruskal演算法求最小生成樹
include include define max vex 100 typedef struct edge edge edgeset max vex 邊集陣列 edgnum max vex 1 int creat return edgnum 排序,使邊集陣列edgeset元素按權值遞增順序排列 v...
kruskal演算法求最小生成樹
kruskal演算法是一種使用貪心思路求解無向圖的最小生成樹的演算法。其大體思路為 將邊按權重排序,然後每次選出權最小且不使圖產生環的邊,作為樹的邊掛上樹。具體來講就是這麼兩個步驟 1.把邊按權重排序。2.依照1的順序遍歷邊 使用乙個並查集來判斷加進這條邊後圖中是否有環。如果沒有環,更新並查集,並把...
kruskal演算法求最小生成樹
描述 要求對乙個圖使用kruskal演算法求最小生成樹,依次輸出選出的邊所關聯的頂點序列,要求下標較小者在前,如圖所示,其頂點序列為1 3 4 6 2 5 3 6 2 3 輸入若干行整數 第一行為兩個整數,分別為圖的頂點數和邊數 第二行開始是該圖的鄰接矩陣,主對角線統一用0表示,無直接路徑的兩點用1...