最小生成樹(MinSpanTree)的Kruskal演算法
分析
最小生成樹的克魯斯卡爾(Kruskal)演算法實現主要是通過將輸入的圖的邊存在優先佇列中,然後依次從優先佇列中取最小的邊加入生成樹,最小生成樹的邊的個數是頂點數減一,因此退出條件是
while (!pq.empty() || cnt < n - 1)
,其中需要注意的是在定義邊結點EdgeNode
時需要過載運算子<
,因為在優先佇列priority_queue
中的實現邏輯就是需要比較元素的大小,那麼在自定義結構體中則需要過載該運算子。
另外一個知識點就是並查集,這個資料結構的實現方式比較簡單,類似於樹的實現方式,具體知識可參考資料。總的來說,Kruskal演算法的實現還是相對簡單的。
C/C++程式碼實現
/*******************************************************
* Kruskal演算法實現最小生成樹
********************************************************/
#include<iostream>
#include<queue>
using namespace std;
const int maxn = 100;
int prev_[maxn];
int vexs[maxn];
int n;//頂點數
int m;//邊數
struct EdgeNode {
int u, v;// u -> v
int weight;//邊權值
/*對於常量型成員變數和引用型成員變數 此處成員變數都是普通成員變數 哪種方法初始化都行
必須通過初始化化列表的方式進行初始化
在建構函式體內進行賦值的方式是行不通的*/
EdgeNode(const int& u, const int& v, const int& weight) :u(u), v(v), weight(weight) {}//建構函式
bool operator < (const EdgeNode& en) const {
return en.weight < this->weight; //最小值優先 建立堆元素升序排列
}
};
class UnionFind {
public:
UnionFind(const int& n);
int Find(const int& p);
void Union(const int& p, const int& q);
};
UnionFind::UnionFind(const int& n)
{
for (int i = 0; i < n; i++)
{
prev_[i] = i;//父節點初始化為自己
}
}
void UnionFind::Union(const int& p, const int& q)
{
int x = Find(p); //找到p的祖先為x
int y = Find(q); //找到q的祖先為y
if (x != y)//不屬於同一組
{
prev_[y] = x; //p, q 合併到一組
}
}
int UnionFind::Find(const int& p)
{
if (prev_[p] == p)
return p;//找到祖先
return Find(prev_[p]);
}
int LocateVertex(int v)
{
for (int i = 0; i < n; i++)
{
if (v == vexs[i])
{
return i;
}
}
return -1;
}
void MinSpanTree_Kruskal(priority_queue<EdgeNode>& pq)
{
int cnt = 0;
UnionFind UF(n);
while (!pq.empty() || cnt < n - 1)//MST的邊數為 頂點數 - 1
{
EdgeNode en = pq.top();
pq.pop();
int u = LocateVertex(en.u);//定位頂點索引
int v = LocateVertex(en.v);
int x = UF.Find(u);
int y = UF.Find(v);
if (x != y) //兩個頂點不屬於同一組
{
UF.Union(x, y);//合併兩頂點
cnt++; //加入一條邊
cout << "加入邊(" << vexs[u] << "," << vexs[v] << "); 邊長為" << en.weight << "." << endl;
}
}
}
int main()
{
int u[maxn];//起始點
int v[maxn];//終止點
int w[maxn];//權值
cout << "請輸入頂點數(n >= 2):";
cin >> n;
cout << "請輸入邊數(m >= n - 1):";
cin >> m;
cout << "請輸入邊依附的頂點及權值資訊:" << endl;
for (int i = 0; i < n; i++)
{
vexs[i] = i + 1;
}
priority_queue<EdgeNode> pq;
for (int i = 0; i < m; i++)
{
cin >> u[i] >> v[i] >> w[i];
EdgeNode en(u[i], v[i], w[i]);
pq.push(en);//建立小頂堆 邊按權值進行升序排列
}
MinSpanTree_Kruskal(pq);
return 0;
}
輸出結果
請輸入頂點數(n >= 2):6
請輸入邊數(m >= n - 1):10
請輸入邊依附的頂點及權值資訊:
1 2 6
1 3 1
1 4 5
2 3 5
2 5 3
3 4 5
3 5 6
5 6 6
3 6 4
4 6 2
加入邊(1,3); 邊長為1.
加入邊(4,6); 邊長為2.
加入邊(2,5); 邊長為3.
加入邊(3,6); 邊長為4.
加入邊(2,3); 邊長為5.
相關文章
- Kruskal 最小生成樹演算法演算法
- 【模板】最小生成樹-kruskal
- Matlab生成Kruskal最小生成樹Matlab
- 最小生成樹:Kruskal演算法和Prim演算法演算法
- 最小生成樹-Prim演算法和Kruskal演算法演算法
- 最小生成樹之Prim演算法和Kruskal演算法演算法
- 北極通訊網路——最小生成樹kruskal
- 最小生成樹的演算法演算法
- 最小生成樹,Prim演算法與Kruskal演算法,408方向,思路與實現分析演算法
- 東哥帶你刷圖論第五期:Kruskal 最小生成樹演算法圖論演算法
- 最小生成樹---普里姆演算法(Prim演算法)和克魯斯卡爾演算法(Kruskal演算法)演算法
- 最小生成樹__Kurskal演算法演算法
- 最小生成樹__Prim演算法演算法
- 關於圖的最小生成路徑——Kruskal演算法和Prime演算法演算法
- 最小樹形圖(有向圖的最小生成樹)朱劉演算法演算法
- 最小生成樹之 Prim 演算法演算法
- 【演算法學習】最小生成樹演算法
- 演算法-圖論-最小生成樹演算法圖論
- 圖論中的最小生成樹演算法圖論演算法
- 最小生成樹
- 最小生成樹——Prim演算法和Kruscal演算法演算法
- 最小生成樹prim普里姆演算法演算法
- 最小生成樹之普里姆演算法演算法
- Boruvka求最小生成樹(菠蘿演算法)演算法
- 最小度限制生成樹
- 【模板】最小生成樹
- 演算法學習之路|最小生成樹——prime演算法演算法
- 前端必會演算法 - 最小生成樹問題前端演算法
- 【圖論】最小生成樹圖論
- 最小生成樹專項
- 圖論 最小生成樹圖論
- 如何在 Java 中實現最小生成樹演算法Java演算法
- 【JAVA演算法】圖論演算法 --求最小生成樹Prim演算法Java演算法圖論
- Kruskal 重構樹
- Kruskal重構樹
- Prim 最小生成樹 圖解圖解
- 最小生成樹的性質與prim演算法(C++實現)演算法C++
- 資料結構與演算法之最好學的最小生成樹資料結構演算法