求最小生成樹 Kruskal演算法和Prim演算法

2022-07-31 13:48:19 字數 3839 閱讀 3764

給定乙個帶權值的無向圖,要求權值之和最小的生成樹,常用的演算法有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 

#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演算法(**還沒理解)

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 

#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演算法適用於邊稀疏的情況(要進行排序),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...