ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

Kruskal算法

2021-09-04 11:04:02  阅读:207  来源: 互联网

标签:mymax int Kruskal spotNum ++ 算法 line 节点


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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有