Kruskal algorithm minimum spanning tree

Kruskal algorithm

  • The origin of Kruskal's
    Prim algorithm uses the properties of MST: suppose N= (V, E) is a connected graph, U is a non-empty subset of the vertex set V, if (u, v) is an edge with the smallest weight, where If u belongs to U and v belongs to VU, there must be a minimum spanning tree containing (u, v).

  • The realization of
    Kruskal algorithm The construction process of Kruskal algorithm
    Assume that the connected network N=(V, E), arrange the edges in N in the order of weight from small to large.

    ① The initial state is a non-connected graph T=(v, {}) with only n vertices and no edges. Each vertex in the graph forms a connected component by itself.

    ②Select the edge with the smallest weight in E. If the vertex attached to the edge falls on a different connected component in the middle (that is, no division is formed), then this edge is added to the work, otherwise the edge is discarded and the next An edge with the smallest weight.

    (3) Repeat ② until all vertices in T are on the same connected component.
    Auxiliary array :

		//辅助数组
		typedef struct
		{
    
    
			string head;//边的起点
			string tail;//边的终点
			int weight;//边的权值
		}Edge[MVNum],EDGE;
		
		int VexSet[MVNum];//标识各个顶点所属的连通分量
		//辅助数组
	

legend
Insert picture description here

  • The implementation step of Kruskal algorithm
    (1) Sort the elements in the array Edge according to the weight from small to large.
    (2) View the edges in the array Edge in turn, and perform the following operations in a loop:

    • Select an edge (U1, U2) from the sorted array Edge in turn;

    • Find the connected components vs1 vs2 where v1 and v2 are located in Vexset to judge;

      • If vs1 vs2 is not equal, it indicates that the selected two vertices belong to different connected components, output this edge, and merge the connected components of vs1 vs2. (That is, no closed loop is formed)

      • If vs1 vs2 are equal, it means that the selected two vertices belong to the same connected component and belong to the same connected component. This edge is discarded and the next edge with the smallest weight is selected. (Formed a closed loop)

  • operation result
    Insert picture description here

  • Implementation code
    ( implementation of adjacency matrix and adjacency list respectively)

	#include<iostream>
	#include<string>
	using namespace std;
	
	#define OK 1
	#define ERROR 0
	#define MAXint 32767 //表示无穷大
	#define MVNum 100	//最大顶点数
	
	//邻接矩阵的结构
	typedef struct
	{
    
    
		string vexs[MVNum];//顶点表
		int arcs[MVNum][MVNum];//邻接矩阵,也就是表示边的权值
		int vexnum, arcnum;//图的顶点数和边的个数
	}AMGraph;
	//邻接矩阵的结构
	
	//邻接表的结构
	typedef struct ArcNode {
    
    //边结点
		int adjvex;//该边所指向的顶点的位置
		struct  ArcNode* nextarc;//指向下一条边的指针
		int info;//和边相关的信息
	}ArcNode;
	
	typedef struct {
    
    //顶点信息
		string data;
		ArcNode* firstarc;//指向第一条依附该顶点的边的指针
	}VNode, AdjList[MVNum];
	
	typedef struct//邻接表
	{
    
    
		AdjList vertices;//顶点信息
		int vexnum, arcnum;//图的当前顶点数和边数
	}ALGraph;
	//邻接表的结构
	
	int Locate(ALGraph G, string v)//Locate重载
	{
    
    
		for (int i = 0; i < G.vexnum; i++)
		{
    
    
			if (G.vertices[i].data == v)
			{
    
    
				return i;
			}
		}
		return -1;
	}
	
	//辅助数组
	typedef struct
	{
    
    
		string head;//边的起点
		string tail;//边的终点
		int weight;//边的权值
	}Edge[MVNum],EDGE;
	
	int VexSet[MVNum];//标识各个顶点所属的连通分量
	//辅助数组
	
	Edge edge;
	
	//查询结点位置
	int Locate(AMGraph G, string v)
	{
    
    
		for (int i = 0; i < G.vexnum; i++)
		{
    
    
			if (G.vexs[i] == v)
			{
    
    
				return i;
			}
		}
		return -1;
	}
	//查询结点位置
	
	
	//创建邻接矩阵
	int CreateUDN(AMGraph& G)//无向图的构造
	{
    
    
		cout << "请输入图的顶点数和边数:";
		cin >> G.vexnum >> G.arcnum;
		cout << "请输入各点的信息:";
		for (int i = 0; i < G.vexnum; i++)
		{
    
    
			cin >> G.vexs[i];
		}
		for (int i = 0; i < G.vexnum; i++)//初始化边的权值为MAXINT
		{
    
    
			for (int j = 0; j < G.vexnum; j++)
			{
    
    
				G.arcs[i][j] = MAXint;
			}
		}
		cout << "各边的顶点信息和权值:";
		for (int k = 0; k < G.arcnum; k++)//构造邻接矩阵
		{
    
    
			string v1, v2;
			int w;//边的两个顶点以及权值
			cin >> v1 >> v2 >> w;
			edge[k] = {
    
     v1,v2,w };
			int i = Locate(G, v1);//找到点的位置
			int j = Locate(G, v2);
			G.arcs[i][j] = w;//赋予权值
			G.arcs[j][i] = G.arcs[i][j];
		}
		return OK;
	}
	//创建邻接矩阵
	
	//创建邻接表
	int CreateUDG(ALGraph& G)
	{
    
    
		cout << "请输入图的顶点数和边数:";
		cin >> G.vexnum >> G.arcnum;//输入顶点数和边数
		cout << "请输入各顶点的信息:";
		for (int i = 0; i < G.vexnum; i++)//初始化顶点信息
		{
    
    
			cin >> G.vertices[i].data;//输入顶点的信息
			G.vertices[i].firstarc = NULL;//firstarc置空
		}
		cout << "请输入各边的两顶点信息和权值:";
		for (int k = 0; k < G.arcnum; k++)
		{
    
    
			string v1, v2;
			int weight;//权值
			cin >> v1 >> v2 >> weight;//输入一条边依附的两个顶点
			edge[k] = {
    
     v1,v2,weight };
			int i = Locate(G, v1);
			int j = Locate(G, v2);
			ArcNode* p1 = new ArcNode;
			p1->info = weight;
			p1->adjvex = j;
			p1->nextarc = G.vertices[i].firstarc;
			G.vertices[i].firstarc = p1;
			ArcNode* p2 = new ArcNode;
			p2->info = weight;
			p2->adjvex = i;
			p2->nextarc = G.vertices[j].firstarc;
			G.vertices[j].firstarc = p2;
		}
		return OK;
	}
	//创建邻接表
	
	void Sort(Edge &edge,int len)
	{
    
    
		for (int i = 0; i < len-1; i++)
		{
    
    
			for (int j = i + 1; j < len; j++)
			{
    
    
				if (edge[i].weight > edge[j].weight)
				{
    
    
					EDGE d = edge[i];
					edge[i] = edge[j];
					edge[j] = d;
				}
			}
		}
	}
	
	//Kruskal最小生成树
	void MiniSpanTree_Kruskal(AMGraph G)
	{
    
    
		Sort(edge, G.arcnum);//将数组edge中的元素按权值大小从小到大排序
		for (int i = 0; i < G.vexnum; i++)//辅助数组,表示各顶点自成一个连通分量
		{
    
    
			VexSet[i] = i;
		}
		for (int i = 0; i < G.arcnum; i++)
		{
    
    
			int head = Locate(G, edge[i].head);//head为边的始点Head的下标
			int tail = Locate(G, edge[i].tail);//tail为边的始点Tail的下标
			int v1 = VexSet[head];//获取边Edge[i]的始点所在的连通分量
			int v2 = VexSet[tail];//获取边Edge[i]的始点所在的连通分量
			if (v1 != v2)//边的两个顶点分属不同的连通分量
			{
    
    
				cout << edge[i].head << "-" << edge[i].tail << endl;//输出边的信息
				for (int j = 0; j < G.vexnum; j++)//合并连通分量
				{
    
    
					if (VexSet[j] == v2)
					{
    
    
						VexSet[j] = v1;
					}
				}
			}
		}
	}
	//Kruskal最小生成树
	
	//Kruskal最小生成树
	void MiniSpanTree_Kruskal(ALGraph G)
	{
    
    
		Sort(edge, G.arcnum);//将数组edge中的元素按权值大小从小到大排序
		for (int i = 0; i < G.vexnum; i++)//辅助数组,表示各顶点自成一个连通分量
		{
    
    
			VexSet[i] = i;
		}
		for (int i = 0; i < G.arcnum; i++)
		{
    
    
			int head = Locate(G, edge[i].head);//head为边的始点Head的下标
			int tail = Locate(G, edge[i].tail);//tail为边的始点Tail的下标
			int v1 = VexSet[head];//获取边Edge[i]的始点所在的连通分量
			int v2 = VexSet[tail];//获取边Edge[i]的始点所在的连通分量
			if (v1 != v2)//边的两个顶点分属不同的连通分量
			{
    
    
				cout << edge[i].head << "-" << edge[i].tail << endl;//输出边的信息
				for (int j = 0; j < G.vexnum; j++)//合并连通分量
				{
    
    
					if (VexSet[j] == v2)
					{
    
    
						VexSet[j] = v1;
					}
				}
			}
		}
	
	}
	int main()
	{
    
    
		ALGraph G;
		CreateUDG(G);
		cout << "请输入最小生成树的起点";
		string v;
		cin >> v;
		MiniSpanTree_Kruskal(G);
		return 0;
	}

Guess you like

Origin blog.csdn.net/m0_43456002/article/details/104381938
Recommended