データ構造-グラフの最小スパニングツリーと最大スパニングツリーのプリムアルゴリズムの理解と実装

プリムのアルゴリズムは、接続されているすべてのツリーの重みの最小合計を見つけるアルゴリズムです。

パスが、
n-1個のパスを必要とするn個の頂点を持つ複数のツリー間の各通信パスに対して正しい値を持っている場合、各ノードが接続され
、最小パスに重みを付けるn-1
-------
ステップ1:
保存された頂点座標連想配列adjvex [ver]を
初期化すると、低コスト[ver]に保存された頂点と関連する権利に対応するエッジ値が初期化されます

最初の選択ポイントとして頂点を選択します。通常は最初または最後の頂点です。ここで最初の頂点Aを選択します

ステップ2:
2つのアレイを初期化する

Aに関連する重みをlowcost [ver]配列に格納し(存在しない場合、INFは無限大です)、lowcost [ver]の値をAの添え字0に
設定します

ステップ3
大きなループに入ります
{ Aの関連するエッジの重みが最小のループを見つけ、その頂点Bを選択し、頂点Bをマークして、その位置kを書き留めます。

次に、Bの周りの重みを探し元の配列lowcost [ver]の対応する位置と比較し(接続がないため、無限大です)、小さい方を選択してlowcost [ver]を求めます
つまり、選択されたBになります関連する重みによって選択されます

次に、adjvex [ver]使用して、関連するウェイトの位置でのBの位置を記録します。

((最後に、上記のサイクルに戻ってBに関連する重みを選択します(場所の選択は処理されていないため、Aの関連する重みも含めることが重要です)))
}

ラベルは選択されるたびにマーク付けられ、再度選択することはできません。

グラフ構造

#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算法生成最小生成树*/
//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;
			}
		}

	}
}

主な機能

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

最大スパニングツリーの原理は同じですが、ここでは、パスなしでINFを無限小に変更する必要があります。

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;
			}
		}
	}
}

おすすめ

転載: blog.csdn.net/weixin_46096297/article/details/113529462