图——普里姆算法——构建最小生成树(采用邻接矩阵的方式存储)

include "stdafx.h"

#include<iostream>
#include<vector>
#include<string>
#include<queue>
#include<stack>
#include<cstring>
#include<string.h>
#include<deque>
#include <forward_list>
#include<set>
#include<list>

using namespace std;

typedef struct
{
	vector<int> vexs;//顶点表
	vector<vector<int>> arcs;//边表
	int vexnums, arcnums;
}AMGraph; //邻接矩阵表示一个图

class Solution {
public:
	void CreateGraph(AMGraph &G)
	{
		int num = 0;
		cout << "请输入顶点个数:";
		cin >> num;
		G.vexnums = num;
		cout << "请输入边的个数:";
		cin >> num;
		G.arcnums = num;
		//依次输入各个顶点
		cout << "依次输入各个顶点:" << endl;
		for (int i = 0; i < G.vexnums; ++i)
		{
			int ch;
			cin >> ch;
			G.vexs.push_back(ch);
		}
		for (int i = 0; i < G.vexnums; ++i)//初始化各个边
		{
			vector<int> vec;
			vec.clear();
			for (int j = 0; j < G.vexnums; ++j)
			{
				vec.push_back(0);
			}
			G.arcs.push_back(vec);

		}
		cout << "依次输入两个关联的顶点:" << endl;
		for (int i = 0; i < G.arcnums; ++i)
		{
			int vex1;
			int vex2;
			cin >> vex1 >> vex2;
			G.arcs[vex1][vex2] = 1;
			G.arcs[vex2][vex1] = 1;//
			cout << "一条边构建成功!" << endl;
		}
		GetGraph(G);
	}

	//为了试验方便,我们自己创建一个固定的图
	void CreatAGraph(AMGraph &G)
	{
		//创建顶点
		G.vexnums = 6;
		G.arcnums = 6;
		for (int i = 0; i < G.vexnums; ++i)
		{
			G.vexs.push_back(i);
		}
		for (int i = 0; i < G.vexnums; ++i)//初始化各个边
		{
			vector<int> vec;
			vec.clear();
			for (int j = 0; j < G.vexnums; ++j)
			{
				vec.push_back(0);
			}
			G.arcs.push_back(vec);
		}
		G.arcs[0][1] = 6;
		G.arcs[1][0] = 6;
		G.arcs[0][2] = 1;
		G.arcs[2][0] = 1;
		G.arcs[0][3] = 5;
		G.arcs[3][0] = 5;

		G.arcs[1][2] = 5;
		G.arcs[2][1] = 5;
		G.arcs[1][4] = 3;
		G.arcs[4][1] = 3;

		G.arcs[2][4] = 6;
		G.arcs[4][2] = 6;
		G.arcs[2][5] = 4;
		G.arcs[5][2] = 4;

		G.arcs[3][2] = 5;
		G.arcs[3][2] = 5;
		G.arcs[3][5] = 2;
		G.arcs[5][3] = 2;
		

		G.arcs[4][5] = 6;
		G.arcs[5][4] = 6;

		GetGraph(G);
	}


	vector<int> visited;//用来标注对应的节点是否被访问,如果被访问,则访问下一个节点
	void DFSTraverse(AMGraph G)//深度优先遍历
	{
		visited.clear();
		//初始化,假设每个节点都没有被访问
		for (int i = 0; i < G.vexnums; ++i)
		{
			visited.push_back(0);//没访问的都设置为0,访问过的都设置为1
		}
		for (int v = 0; v < G.vexnums; ++v)
		{
			if (visited[v] == 0)//保证节点没有被访问
				DFS(G, v);
		}
		cout << endl;
	}
	void DFS(AMGraph G, int v) //对i节点进行深度优先遍历
	{
		cout << "v_" << v << "  ";
		visited[v] = 1;
		for (int i = 0; i < G.vexnums; ++i)
		{
			if (G.arcs[v][i] != 0 && visited[i] == 0)//存在边,且i节点没有访问过
				DFS(G, i);
		}
		return;
	}

	void  BFSTraverse(AMGraph G)//广度优先遍历
	{
		visited.clear();
		for (int i = 0; i < G.vexnums; ++i)
		{
			visited.push_back(0);//没访问的都设置为0,访问过的都设置为1
		}
		for (int v = 0; v < G.vexnums; ++v)
		{
			if (visited[v] == 0 )
			{
				cout << "v_" << v << "  ";//节点没有被访问
				visited[v] = 1;
			}
			for (int i = 0; i < G.vexnums; ++i)
			{
				if (visited[i] == 0 && G.arcs[v][i] != 0)
				{
					cout << "v_" << i << "  ";//节点没有被访问
					visited[i] = 1;
				}
			}
		}
		cout << endl;
	}
	void BFS(AMGraph G, int v)
	{
		if (visited[v] == 0)
		{
			cout << "v_" << v << "  ";//节点没有被访问
			visited[v] = 1;
		}

		for (int i = 0; i < G.vexnums; ++i)
		{
			if (visited[i] == 0)
			{
				cout << "v_" << v << "  ";//节点没有被访问
				visited[v] = 1;
			}
		}
	}

	void  GetGraph(AMGraph G)
	{
		cout << "顶点信息:" << endl;
		for (int i = 0; i < G.vexnums; ++i)
		{
			cout << G.vexs[i] << "  ";
		}
		cout << endl;
		cout << "边的信息:" << endl;
		for (int i = 0; i < G.vexnums; ++i)
		{
			for (int j = 0; j < G.vexnums; ++j)
			{
				cout << G.arcs[i][j] << "  ";
			}
			cout << endl;
		}
	}
	//用普利姆算法构建最小生成树,最小生成树存在返回T
	vector<int>nodes;//存储已经存在在U集合里面的点,每次从剩下的节点选择离nodes集合里面距离最小的节点
vector<int>renodes;//存储剩余的节点

	AMGraph  MinSpanTree_Prim(AMGraph G)
	{
		
		AMGraph T;
		T.vexnums = G.vexnums;
		//初始化顶点
		for (int i = 0; i < T.vexnums; ++i)
		{
			T.vexs.push_back(i);
		}
		//初始化边
		for (int i = 0; i < T.vexnums; ++i)
		{
			renodes.push_back(i);//向renodes中插入节点
			vector<int> vec;
			
			for (int j = 0; j < T.vexnums; ++j)
			{
			//	T.arcs[i][j] = 0;   //初始化T
			
				vec.push_back(0);
			}
			T.arcs.push_back(vec);
		}
		
		//从v_0开始选边
		nodes.push_back(0);//第0个边给node节点
		renodes.erase(renodes.begin()+0);

	
		while (nodes.size()!=T.vexnums)
		{
			int minDistance = G.arcs[nodes[0]][renodes[0]];//记录最小距离
		
			int minNode1 = nodes[0];
			int minNode2 = renodes[0];//记录离最小距离的节点
			int flag = 0;//renodes中要删除的节点
			bool visist = false;
			int i = 0, j = 0;
			for ( i = 0; i < nodes.size(); ++i)//选择距离最小的边
			{
				for ( j = 0; j < renodes.size(); ++j)
				{
					//找到最小距离,且最小距离和原来节点不形成回路
					//if (visist == false && minDistance==0 && G.arcs[nodes[i]][renodes[j]] != 0 ) //距离不等于0 //只执行一次,找到最短距离
					if ( minDistance == 0 && G.arcs[nodes[i]][renodes[j]] != 0) //距离不等于0 //只执行一次,找到最短距离
					{
						minDistance = G.arcs[nodes[i]][renodes[j]];
						minNode1 = nodes[i];
						minNode2 = renodes[j];
						flag = j;
					//	visist = true;  //visit保证这条语句只访问一次
					//	cout << "flag:" << flag << endl;
					}
					if (G.arcs[nodes[i]][renodes[j]] != 0 && minDistance > G.arcs[nodes[i]][renodes[j]])
					{
						minDistance = G.arcs[nodes[i]][renodes[j]];
					minNode1 = nodes[i];
						minNode2 = renodes[j];
						flag = j;
					//	cout << "flag:" << flag << endl;
					}
					
				}
			//	cout << "最短距离是:" << minDistance << endl;
			}
			
			T.arcs[minNode1][minNode2] = minDistance;
			T.arcs[minNode2][minNode1] = minDistance;
			T.arcnums++;
			nodes.push_back(minNode2);
			//cout << "flag:" << flag << endl;
			cout << "nodes:" ;
			print(nodes);
			cout << endl;
			
			renodes.erase(renodes.begin()+flag);
			//cout << "renodes:";
			//print(renodes);
			//cout << endl;
			//cout << endl;
			//cout << "T.vexnums:" << T.vexnums;
			//cout << "nodes.size():" << nodes.size();
		}
		return T;
	}
	void print(vector<int> vec)
	{
		for (int i = 0; i < vec.size(); ++i)
			cout << vec[i] << "  ";
	}
	//用克鲁斯算法构建最小生成树,最小生成树返回T
	/*AMGraph MinSpanTree_Kruskal(AMGraph G)
	{

	}*/
};
int main()
{


	Solution so;

	AMGraph G;
	//so.CreateGraph(G);
	so.CreatAGraph(G);
	cout << "G深度优先遍历:" << endl;
	so.DFSTraverse(G);

	cout << "G广度优先遍历:" << endl;
	so.BFSTraverse(G);
	//so.GetGraph(G);

	AMGraph T;
	T = so.MinSpanTree_Prim(G);
	cout << "T深度优先遍历:" << endl;
	so.DFSTraverse(T);
	cout << "T的信息:" << endl;
	so.GetGraph(T);

	return 0;
}
原文地址:https://www.cnblogs.com/wdan2016/p/6183844.html