Java教程

Kruskal算法

本文主要是介绍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;
}
这篇关于Kruskal算法的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!