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

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

クラスカルアルゴリズムの理解:

n個の頂点の最小パスの場合、スパニングツリーにはn-1個のパスがあります。

まず、頂点を小さいものから大きいものへと重みで配置します。

次に、最小のものから重みを選択します

選択する親配列を設定します。
これは、親が毎回変更されることを意味します

ただし、パスの場合、末尾が親の同じ位置の値に対応している場合は、頂点が2回取得されることを意味します。

隣接行列とエッジセット配列を定義します

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

//定义边集数组Edge
typedef struct EdgeNode{
    
    
	int begin;
	int end;
	int weight;
}EdgeNode, *Edge;//这个数组一定要固定吗  开始我这里是写的固定数组 改成这样后面加上一个new即可变成动态数组

Status Find(int *parent, int f);

グラフを生成する

//生成图——邻接矩阵
Status CreatGraph(MGraph &G)
{
    
    
	int i, j, 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;
}

//隣接行列をエッジセット配列に変換します

隣接行列に対称性があり、主対角要素がトラバーサル割り当てに存在しない場合は注意してください

Status GraphToEdge(MGraph &G, Edge *edges)
{
    
    
	EdgeNode *t;
	int i, j,k=0;
	//观察邻接矩阵的结构  主对角线不存在  只遍历一半即可
	for (i = 0; i < G.NumVer; i++)
		for (j = i+1; j < G.NumVer; j++){
    
    
		if (G.Arc[i][j] != INF){
    
    //权值存在
			edges[k] = new EdgeNode;
			edges[k]->begin = i;
			edges[k]->end = j;
			edges[k]->weight = G.Arc[i][j];
			k++;
		}
		}
	//cout << k << endl << endl;

	//冒泡排序
	for (i = 0; i < G.NumEdg - 1; i++)
		for (j = 0; j < G.NumEdg - i - 1;j++)
			if (edges[j]->weight > edges[j + 1]->weight){
    
    
			t = edges[j];
			edges[j] = edges[j+1];
			edges[j + 1] = t;
			}

	/*for (i = 0; i < G.NumEdg; i++){
		cout << edges[i].weight << endl;
	}*/
	return 0;
}

クラスカルアルゴリズム

親の手のアニメーションのより良い理解

Status MinSpanTree(MGraph &G,Edge *edges)
{
    
    
	int i, n, m;
	int parent[MAXVER];
	for (i = 0; i < G.NumVer; i++)
		parent[i] = 0;
	for (i = 0; i < G.NumEdg; i++)
	{
    
    
		n = Find(parent, edges[i]->begin);//选择首尾下标
		m = Find(parent,edges[i]->end);

		if (m != n)//判断是否循环  这里画图更容易理解
		{
    
    
			parent[n] = m;
			cout << edges[i]->begin << "____" << edges[i]->end << "____" << edges[i]->weight << endl;
		}
	}
	return 0;
}

Status Find(int *parent, int f)
{
    
    
	while (parent[f]>0)
	{
    
    
		f = parent[f];
	}
	return f;
}


int main()
{
    
    
	MGraph G;
	Edge *edges=(Edge *)malloc(sizeof(EdgeNode));
	CreatGraph(G);
	GraphToEdge(G,edges);
	MinSpanTree(G,edges);
	system("pause");
	return 0;
}

ここに画像の説明を挿入

おすすめ

転載: blog.csdn.net/weixin_46096297/article/details/113559809
おすすめ