Data structure-understanding and implementation of the Prim algorithm of the minimum spanning tree and maximum spanning tree of the graph

Prim's algorithm is an algorithm to find the smallest sum of weights of all connected trees

If the path has the right value for each communication path between the plurality of tree
with n vertices that needs to n-1 paths enables each node are connected
, and n-1 which weights the minimum path
- -----
step 1:
initializing a stored vertex coordinates associated array adjvex [ver]
initializes a vertex and associated rights corresponding edge value stored in lowcost [ver]

Choose a vertex as the first selection point, usually the first or last vertex. Here select the first vertex A

Step 2:
Initialize two arrays

Store the weights related to A into the lowcost[ver] array (if it does not exist, INF is infinite) and
set the values ​​of lowcost[ver] to the subscript 0 of A

Step 3
Enter the big loop
{ find the one with the smallest weight of the related edge of A, select its vertex B, mark vertex B, and write down its position k

Then look for the weight around B and compare it with the corresponding position of the original array lowcost[ver] (because there is no connection, it is infinite), and choose the smaller one to give lowcost[ver]
(in short, it will be the selected B’s Selected by relevant weights )

Then use adjvex[ver] to record the position of B at the position of the relevant weight

((Finally, return to the above cycle to select the weights related to B (it is important to include the related weights of A because the location is selected and has not been processed)))
}

The label will be marked every time it is selected and cannot be selected again.

Graph structure

#include<iostream>
#include <iomanip>
using namespace std;

typedef char Vertextype;//顶点类型
typedef int Edgetype;//边缘权值
typedef int Status;
#define MAXVER 9//最大顶点数
#define INF 65535//代表无穷
#define NULL 0


typedef struct Graph
{
    
    
	Vertextype Ver[MAXVER];
	Edgetype Arc[MAXVER][MAXVER];
	int NumVer, NumEdg;
}MGraph;

Status CreatGraph(MGraph &G)
{
    
    
	int i, j, k, w;
	cout << "Please enter the number of verticesof the graph : " << endl;
	cin >> G.NumVer;
	cout << "Please enter the number of edges the graph : " << endl;
	cin >> G.NumEdg;
	cout << "Please enter the name of vex : " << endl;
	for (i = 0; i < G.NumVer; i++){
    
    
		//cout << "Please enter the NO." << i + 1 << "%d name of vex : " << endl;
		cin >> G.Ver[i];
	}

	cout << "Diagonal infinity ..." << endl;
	for (i = 0; i < G.NumVer; i++)
		for (j = 0; j < G.NumVer; j++)
		{
    
    
		G.Arc[i][j] = INF;//简单图  不循环
		//cout << G.arc[i][j] << endl;//不理解为啥是1
		}
	cout << "...Diagonal infinity" << endl;

	for (int k = 0; k < G.NumEdg; k++){
    
    //因为具体哪条边存在不一定 所以选择性输入边
		cout << "Enter the subscripts and weights from vertex vi to vertex vj : " << endl;
		cin >> i >> j >> w;
		/*cout << "Please enter the subscript j of the edge : " << endl;
		cin >> j;
		cout << "Please enter the weight from vertex "<<i<<" to vertex "<<j<<" : " << endl;
		cin >> w;*/

		G.Arc[i][j] = w;
		G.Arc[j][i] = G.Arc[i][j];//无向图  边的信息  是对称的  //有向图的话 无需设置

	}
	return 0;
}

Prim algorithm implementation

/*prim算法生成最小生成树*/
//Lowcost数组会一直变化,初始化时是0顶点和其他顶点之间的权值(有连线就是有权值 不然为INF无穷大)
//后面LC数组会记录下被选择权重最小的那个顶点相关的权重

//Adjvex数组也会一直变化  初始化时是都是0
//会记录下顶点相关权重位置
void MinSpanTree(Graph &G)
{
    
    
	int min, i, j, k;
	int Adjvex[MAXVER];		//保存相关顶点下标
	int Lowcost[MAXVER];	//保存相关顶点间边的权值

	/*选取一个顶点 加入最小生成树,选择0是方便后面  所以选择头或尾最好*/
	Lowcost[0] = 0;			//标记为0 就是被选择 后续循环不再用该点
	Adjvex[0] = 0;			
	
	/*取Lowcost数组   存放和第一个生成树顶点相关的权值  若不存在 则默认是INF*/
	for (i = 1; i < G.NumVer; i++){
    
    
		Lowcost[i] = G.Arc[0][i];		//将和第一个生成树顶点相关的权值依次存入数组
		Adjvex[i] = 0;//初始化都为第一个顶点的坐标
	}


//开始了
//先找出第一个顶点权值最小的那个
//然后将该权值的另外一个顶点标记  且用k记录位置
	for (i = 1; i < G.NumVer; i++){
    
    
		min = INF;		//初始化最小权值为INF 
		j = 1, k = 0;	//k用来记录最小权值的边

		while (j < G.NumVer)//从第一个顶点开始寻找
		{
    
    
			if (Lowcost[j] != 0 && Lowcost[j] < min)//相当于寻找合法边 进行比较找到最小的一个
			{
    
    
				//如果边存在
				min = Lowcost[j];
				k = j;//记录最小权值的边
			}
			j++;
		}

		cout <<k <<"-----"<<Adjvex[k]<< endl;//打印最小权值的位置   但是这个Ad有什么用呢

		Lowcost[k] = 0;//将此位置的顶点标记存入最小生成树的数组中后续将不再被判断  因为顶点走过一次就想
		
		//这里是更新  LC 和Ad   将上面选择的最小的顶点  的相关权值取代之前的LC里面的值      Ad为记录位置
		for (j = 1; j < G.NumVer; j++){
    
    //循环所有顶点 
			if (Lowcost[j] != 0 && G.Arc[k][j] < Lowcost[j]){
    
    
				//没有标记过的顶点   
				Lowcost[j] = G.Arc[k][j];
				Adjvex[j] = k;
			}
		}

	}
}

Main function

int main()
{
    
    
	Graph G;
	CreatGraph(G);
	MinSpanTree(G);
	MaxSpanTree(G);
	system("pause");
	return 0;
}

The principle of maximum spanning tree is the same, but here we need to change the INF without path to infinitesimal

void MaxSpanTree(Graph &G)
{
    
    
	int max, i, j, k;
	int adj[MAXVER];
	int maxcost[MAXVER];

	maxcost[0] = 0;
	adj[0] = 0;

	//将无路径设置为无穷小
	for (i = 0; i < G.NumVer; i++)
	{
    
    
		for (j = 0; j < G.NumVer; j++)
		{
    
    
			if (G.Arc[i][j] == INF)
			{
    
    
				G.Arc[i][j] = -1;
			}
		}
	}
		

	//初始化

	for (i = 1; i < G.NumVer; i++)
	{
    
    
		maxcost[i] = G.Arc[0][i];
		adj[i] = 0;
	}

	for (i = 0; i < G.NumVer; i++)
	{
    
    
		max = 0;
		j = 1; k = 0;
		while (j < G.NumVer)
		{
    
    
			if (maxcost[j] != 0 && maxcost[j] > max)
			{
    
    
				max = maxcost[j];
				k = j;
			}
			j++;
		}

		cout << k << "----" << adj[k] << endl;
		maxcost[k] = 0;//标记
		for (j = 1; j < G.NumVer; j++)
		{
    
    
			if (maxcost[j] != 0 && G.Arc[k][j] > maxcost[j])
			{
    
    
				maxcost[j] = G.Arc[k][j];
				adj[j] = k;
			}
		}
	}
}

Guess you like

Origin blog.csdn.net/weixin_46096297/article/details/113529462