Kruskal算法
作者:互联网
kruskal算法的思想简单说来就是:每次选择图中最小边权的边,如果边两端的顶点在不同的连通块中,就把这条边加入最小生成树中
为此,我们需要将边权值进行排序
结点结构
图:
点集---数据类型据需求而定
边集---结构体数组
点数
边数
边集:
from---出发的节点
to---到达的结点
weight---权值
对权值进行排序
这里我们采用冒泡排序;当然也可以用其他的,比如sort函数(include<algorithm>),需要注意的是,由于是结构体数组,数据类型不是基本数据类型,所以使用sort函数时,需要自定义一个大小比较比如cmp(Edge*edge,int len)
Kruskal
我们需要一个parent数组来记录节点的根节点;由此,我们把每一个节点都划分成为一个集合,即parent[i]=i;再进行权值排序;我们通过查找权值的from与to(由小到大的排序可以保证最小生成树的总权值最小)的根节(findRoot)点来观察当前两个节点是否会形成环(如果找到的两个根节点不相同,就不会形成环),若不会形成环,就把当前边权加上;再合并当前这两个节点,即parent[vex2]=vex1;(vex2的根节点是vex1,也可以反过来)若两个节点合并成功,则num++,因为第一个节点直接就加入到最小生成树的集合中,所以只要判断num是否等于点的个数-1就行了
findRoot
首先,如果parent[i]=i,则代表当前的i就是根节点;而parent[vex2]=vex1记录了vex2的根节点是vex1,所以需要一个判断语句if(x=parent[x])如果相等,就直接返回parent[x];否则就进行递归寻找他的根节点,并赋给parent[x],最后可以找到他的根节点
#include<iostream>
#include<string.h>
#include<algorithm>
#define mymax 65535
using namespace std;
typedef struct Edge
{
int from;
int to;
int weight;
}Edge;
typedef struct Graph
{
int* spot;//点集
Edge* line;//边集
int spotNum;
int lineNum;
int minLength;
}Graph;
bool cmp(Edge a, Edge b)
{
return a.weight < b.weight;
}
void bubbleSort(Edge* a, int len)
{
for (int i = 0; i < len - 1; i++)
{
for (int j = 0; j < len - 1 - i; j++)
{
if (a[j].weight > a[j + 1].weight)
{
Edge temp;
temp = a[j + 1];
a[j + 1] = a[j];
a[j] = temp;
}
}
}
}
Graph* initGraph(int dianshu)
{
Graph* G = new Graph;
G->spotNum = dianshu;
G->lineNum = 0;
G->minLength = 0;
G->spot = new int[dianshu];
return G;
}
void createGraph(Graph* G, int* dian, int* bian)
{
for (int i = 0; i < G->spotNum; i++)
{
G->spot[i] = dian[i];
}
for (int j = 0; j < G->spotNum * G->spotNum; j++)
{
if (bian[j] > 0 && bian[j] < mymax)
{
G->lineNum++;
}
}
G->lineNum /= 2;
G->line = new Edge[G->lineNum];
for (int i = 0; i < G->lineNum; i++)
{
cin >> G->line[i].from >> G->line[i].to >> G->line[i].weight;
}
}
void printLine(Graph* G)
{
int j = 0;
for (int i = 0; i < G->spotNum * G->spotNum; i++)
{
cout << G->line[i].weight << "\t";
j++;
if (j % G->spotNum == 0)
cout << endl;
}
cout << endl;
}
void printSpot(Graph* G)
{
for (int i = 0; i < G->spotNum; i++)
{
cout << G->spot[i] << "\t";
}
cout << endl;
}
int findRoot(int* parent, int x)
{
if (x != parent[x])
{
parent[x] = findRoot(parent, parent[x]);
}
return parent[x];
}
void outputMST(Graph* G, int i)
{
cout << "(" << G->line[i].from << "," << G->line[i].to << ")" << " " << G->line[i].weight << endl;
}
void Kruskal(Graph* G)
{
int* parent = new int[G->spotNum];
for (int i = 0; i < G->spotNum; i++)
{
parent[i] = i;
}
//bubbleSort(G->line,G->lineNum);
sort(G->line, G->line + G->lineNum, cmp);
cout << endl;
cout << "权值升序:";
for (int i = 0; i < G->lineNum; i++)
{
cout << G->line[i].weight << " ";
}
cout << endl;
cout << endl;
cout << "路径:" << endl;;
int num = 0;
for (int j = 0; j < G->spotNum; j++)
{
int vex1 = findRoot(parent, G->line[j].from);//找到生成树的根节点
int vex2 = findRoot(parent, G->line[j].to);
if (vex1 != vex2)//找到的根节点不相同,不会构成环
{
outputMST(G, num);
G->minLength += G->line[num].weight;
parent[vex2] = vex1;//合并生成树
num++;
if (num == G->spotNum - 1)
return;
}
else
{
num++;
}
}
}
int main()
{
int spot[] = { 0,1,2,3,4,5 };
int num = sizeof(spot) / sizeof(int);
Graph* G = initGraph(num);
int bian[] = { 0,34,46,mymax,mymax,19,
34,0,mymax,mymax,12,mymax,
46,mymax,0,17,mymax,25,
mymax,mymax,17,0,38,25,
mymax,12,mymax,38,0,26,
19,mymax,25,25,26,0 };
createGraph(G, spot, bian);
Kruskal(G);
cout << endl;
cout << "最短路径:" << G->minLength << endl;
}
标签:mymax,int,Kruskal,spotNum,++,算法,line,节点 来源: https://blog.csdn.net/m0_57517390/article/details/120096010