[アルゴリズム] 最小スパニングツリーのKruskalアルゴリズム

分析する

最小スパニング ツリー ( ) のMinSpanTreeKruskal Kruskal( ) アルゴリズムの実装は、主に、入力グラフのエッジを優先キューに格納し、優先キューから最小のエッジを取り出してスパニング ツリーに結合することによって行われます。最小スパニング ツリーでは、頂点の数から 1 を引いた値になるため、終了条件は になります。優先キューの実装ロジックはサイズを比較するためwhile (!pq.empty() || cnt < n - 1)エッジ ノードを定義するEdgeNodeときに演算子をオーバーロードする必要があることに注意してください。要素のカスタム構造体で演算子をオーバーロードする必要があります。もう 1 つの知識ポイントは共用体検索です。このデータ構造の実装はツリーの実装と同様で比較的単純です。具体的な知識については資料を参照してください。一般に、クラスカルのアルゴリズムの実装は比較的単純です。<priority_queue

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] = -1;//父节点初始化为-1
	}
}

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]  == -1)
		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 です。
join side(2,5) ; 辺の長さは 3.
join side(3,6); 辺の長さは 4.
join side(2,3); 辺の長さは 5.

おすすめ

転載: blog.csdn.net/qq_41139677/article/details/108926064
おすすめ