一、最小生成树概念
最小生成树是一副连通加权无向图中一棵权值最小的生成树。
二、Prim’s算法
#include <iostream>
#include <cstdlib>
#include <cstdio>
using namespace std;
const int V = 5;
const int MAXX = 1314520;
void printMST(int parent[],int graph[V][V])
{
for(int i = 1;i<V;i++) {
cout<<parent[i]<<"--"<<i<<" == "<<graph[i][parent[i]]<<endl;
}
}
void primMST(int graph[V][V])
{
// 存储最小生成树
int parent[V];
// 用来寻找最小边,初始化为INT_MAX
int num[V];
// 判断节点是否已经在最小生成树中
bool MSTset[V];
for(int i=0;i<V;i++) {
num[i] = MAXX;
MSTset[i] = false;
}
// 设置0为起点
num[0] = 0;
// 设为根节点 ,第一个节点是根节点
parent[0] = -1;
for(int count = 0;count < V-1;count++) {
// 找到num最小且不在MSTset中的节点
int minn = MAXX;
int min_index = 0;
for(int i=0;i<V;i++) {
if((MSTset[i]==false)&&(num[i]<minn)) {
minn = num[i];
min_index = i;
}
}
// 将其加入MSTset
MSTset[min_index] = true;
int u = min_index;
// 更新那些未加入MSTset节点的num的值和parent的地址,
for(int v=0;v<V;v++) {
// u和v是连接的
if(graph[u][v] && MSTset[v]==false && graph[u][v] < num[v]) {
num[v] = graph[u][v];
parent[v] = u;
}
}
}
//输出MST
printMST(parent,graph);
}
int main()
{
int graph[V][V] = { { 0, 1, 0, 3, 0 },
{ 2, 0, 3, 9, 4 },
{ 0, 2, 0, 0, 9 },
{ 5, 7, 0, 0, 8 },
{ 0, 4, 6, 9, 0 } };
primMST(graph);
return 0;
}
三、Kruskal算法
//freopen("hao.txt","r",stdin);
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
using namespace std;
class Edge
{
public:
int src;
int dest;
int weight;
};
class Graph
{
public:
int V; //节点数
int E; //边数
Edge* edge;
};
Graph* createGraph(int V,int E)
{
Graph* graph = new Graph;
graph->V = V;
graph->E = E;
graph->edge = new Edge[E];
return graph;
}
class subset
{
public:
int rank;
int parent;
};
int find(subset subsets[],int i){
if(subsets[i].parent != i)
subsets[i].parent = find(subsets,subsets[i].parent);
return subsets[i].parent;
}
void Union(subset subsets[],int x,int y)
{
int x_root = find(subsets,x);
int y_root = find(subsets,y);
if(subsets[x_root].rank < subsets[y_root].rank)
subsets[x_root].parent = y_root;
else if(subsets[x_root].rank > subsets[y_root].rank)
subsets[y_root].parent = x_root;
else{
subsets[y_root].parent = x_root;
subsets[x_root].rank++;
}
}
int cmp(const void* a,const void* b)
{
Edge* a1 = (Edge*)a;
Edge* b1 = (Edge*)b;
return a1->weight > b1->weight;
}
void Kruskal(Graph* graph)
{
int V = graph->V;
int E = graph->E;
Edge result[V];
int v = 0;
int e = 0;
qsort(graph->edge,graph->E,sizeof(graph->edge[0]),cmp); //排序每一条边从小到大
subset* subsets = new subset[V * sizeof(subset)]; //开辟空间
for(int i=0;i<V;i++) { //初始化subsets
subsets[i].parent = i;
subsets[i].rank = 0;
}
while((v < V-1)&&(e < graph->E)) {
Edge next_edge = graph->edge[e++]; //取出每一条边
int x = find(subsets,next_edge.src);
int y = find(subsets,next_edge.dest);
if(x!=y){ //不在一个集合才能合并,不然成环
result[v++] = next_edge;
Union(subsets,x,y);
}
}
printf("This is result of Kruskal MST:\n");
for(int i=0;i<v;i++)
cout<<result[i].src<<" -- "<<result[i].dest<<" = "<<result[i].weight<<endl;
}
int main()
{
int V = 4;
int E = 5;
Graph* graph = createGraph(V,E);
// add edge 0-1
graph->edge[0].src = 0;
graph->edge[0].dest = 1;
graph->edge[0].weight = 10;
// add edge 0-2
graph->edge[1].src = 0;
graph->edge[1].dest = 2;
graph->edge[1].weight = 6;
// add edge 0-3
graph->edge[2].src = 0;
graph->edge[2].dest = 3;
graph->edge[2].weight = 5;
// add edge 1-3
graph->edge[3].src = 1;
graph->edge[3].dest = 3;
graph->edge[3].weight = 15;
// add edge 2-3
graph->edge[4].src = 2;
graph->edge[4].dest = 3;
graph->edge[4].weight = 4;
Kruskal(graph);
return 0;
}