kruskal算法的思想简单说来就是:每次选择图中最小边权的边,如果边两端的顶点在不同的连通块中,就把这条边加入最小生成树中
为此,我们需要将边权值进行排序
图:
点集---数据类型据需求而定
边集---结构体数组
点数
边数
边集:
from---出发的节点
to---到达的结点
weight---权值
这里我们采用冒泡排序;当然也可以用其他的,比如sort函数(include<algorithm>),需要注意的是,由于是结构体数组,数据类型不是基本数据类型,所以使用sort函数时,需要自定义一个大小比较比如cmp(Edge*edge,int len)
我们需要一个parent数组来记录节点的根节点;由此,我们把每一个节点都划分成为一个集合,即parent[i]=i;再进行权值排序;我们通过查找权值的from与to(由小到大的排序可以保证最小生成树的总权值最小)的根节(findRoot)点来观察当前两个节点是否会形成环(如果找到的两个根节点不相同,就不会形成环),若不会形成环,就把当前边权加上;再合并当前这两个节点,即parent[vex2]=vex1;(vex2的根节点是vex1,也可以反过来)若两个节点合并成功,则num++,因为第一个节点直接就加入到最小生成树的集合中,所以只要判断num是否等于点的个数-1就行了
首先,如果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; }