Kruskal算法是依次选择连接图中两个顶点间权值最小的边来实现的,当所选的边产生圈时就放弃选取该边,算法首先要将所有边的权值从小到大进行排序。
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
int sum;
typedef struct
{
int row, col, val;
} matrix;
typedef struct
{
string *vertexs; // 存储顶点
matrix *edges; // 存储边
int vertex, edge;
} adjmatrix;
void init_graph(adjmatrix & g, int vertex, int edge)
{
g.vertex = vertex;
g.edge = edge;
g.vertexs = new string[g.vertex];
g.edges = new matrix[g.edge];
}
void destroy_graph(adjmatrix & g)
{
delete [] g.vertexs;
delete [] g.edges;
}
bool cmp(const matrix & a, const matrix & b)
{
return a.val < b.val;
}
void create_graph(adjmatrix & g)
{
cout << "Enter vertex in graph:" << endl;
for (int i = 0; i < g.vertex; i++) {
cin >> g.vertexs[i];
}
int x, y, weight;
cout << "Enter A to B and weight in graph:" << endl;
for (int i = 0; i < g.edge; i++) {
cin >> x >> y >> weight;
g.edges[i].row = x;
g.edges[i].col = y;
g.edges[i].val = weight;
}
}
int find_set(int *s, int x)
{
while (s[x] >= 0) {
x = s[x];
}
return x;
}
void union_set(int *s, int x, int y)
{
s[x] = y;
}
void kruskal(adjmatrix & g)
{
sort(g.edges, g.edges + g.edge, cmp);
for (int i = 0; i < g.edge; i++) {
cout << "(" << g.edges[i].row << ", " << g.edges[i].col << ") " << g.edges[i].val << endl;
}
int *s = new int[g.vertex];
for (int i = 0; i < g.vertex; i++) {
s[i] = -1;
}
int i = 0, count = 0;
int x, y;
int p1, p2;
while (1) {
x = g.edges[i].row;
y = g.edges[i].col;
p1 = find_set(s, x);
p2 = find_set(s, y);
if (p1 != p2) {
count++;
cout << "(" << g.vertexs[x] << ", " << g.vertexs[y] << "):" << g.edges[i].val << endl;
sum += g.edges[i].val;
union_set(s, p1, p2);
if (count == g.vertex - 1) {
break;
}
}
i++;
}
}
int main()
{
int vertex, edge;
cout << "Enter the number of vertex and edge of graph:" << endl;
cin >> vertex >> edge;
adjmatrix g;
init_graph(g, vertex, edge);
create_graph(g);
kruskal(g);
destroy_graph(g);
cout << "The total value of the spanning tree is " << sum << endl;
return 0;
}
参考:https://www.bilibili.com/video/BV1Xa4y1i7wu