3.0 基本操作

以下是后文用到的 “__0 Basic_operation.h” 文件,提供一些图与网的基本构造操作

//__0 Basic_operation.h

#ifndef __Basic_operation_h
#define __Basic_operation_h
#include <iostream>
#include <vector>
#include <iomanip>		//格式化打印头文件
#include <algorithm>	//sort算法头文件

using namespace std;

typedef char VertexType;	//顶点类型
typedef int EdgeType;		//边上的权值类型
#define myINFINITY 65535	//用65535代表正无穷
#define N 65535

/*  通过数组建立一个邻接矩阵  *******************************************************************************************/
class MGraph {
public:
	MGraph() : numVertexes(0), numEdges(0) { }
	vector<VertexType> vexs;		//顶点表,存储顶点信息
	vector<vector<EdgeType>> arcs;	//邻接矩阵,作为边表
	int numVertexes, numEdges;		//图中当前的顶点数和边数
};
void CreateMGraphByArray(class MGraph& G, const vector<vector<EdgeType>>& vv, int flag)		//传入非 0 值表示有向图
{
	G.numVertexes = (int)vv.size();	//顶点个数
	G.vexs.resize(G.numVertexes);	//设置顶点数组大小
	G.arcs.resize(G.numVertexes);	//设置矩阵总列数

	char vex = 'A';
	/*开始复制矩阵*/
	for (int i = 0; i < G.numVertexes; ++i) {
		G.arcs[i].resize(G.numVertexes);			//设置矩阵每一行的大小
		for (int j = 0; j < G.numVertexes; ++j) {
			G.arcs[i][j] = vv[i][j];
			if (G.arcs[i][j] != 0 && G.arcs[i][j] < N)
				++G.numEdges;	//边数增加
		}
		G.vexs[i] = vex++;		//为每个顶点附一个值
	}
	if (!flag)				//无向图
		G.numEdges /= 2;	//边总数减半
}

/*打印邻接矩阵*/
void ShowMGraph(const MGraph& G)
{
	std::cout << std::endl << "顶点数: " << G.numVertexes << "  边总数: " << G.numEdges << std::endl;
	std::cout << "     V0";
	for (int i = 1; i < G.numVertexes; ++i)
		std::cout << "  V" << i;
	for (int i = 0; i < G.numVertexes; ++i) {
		if (i < 10)
			std::cout << "\n V" << i;
		else
			std::cout << "\nV" << i;
		for (int j = 0; j < G.numVertexes; ++j) {
			if (G.arcs[i][j] != N)
				std::cout << std::right << std::setw(4) << G.arcs[i][j];
			else
				std::cout << std::right << std::setw(4) << "∞";
		}
		std::cout << "  :" << G.vexs[i];
	}
	std::cout << std::endl;
}


/*  通过邻接矩阵建立邻接表  *******************************************************************************************/

/*边表节点,用于构建链表*/
typedef struct EdgeNode {
	int adjvex;			 //邻接点域,存储该节点对应的下标
	EdgeType weight;	 //用于存储权值
	EdgeNode* next;		 //指向下一邻接点
}EdgeNode;
/*顶点表节点,用于存储顶点*/
typedef struct VertexNode {
public:
	VertexNode() : data('\0'), firstEdge(nullptr), od(0), id(0) { }
	VertexType data;	  //顶点的数据
	EdgeNode* firstEdge;  //边表头指针,指向邻接链表
	int od;				  //顶点的出度
	int id;				  //顶点的入度
}AdjList;
/*邻接表结构体*/
typedef struct {
	vector<AdjList> adjlist;	//顶点数组
	int numVertexes, numEdges;	//图中顶点数和边数
}GraphAdjList;
void CreateAdjListByMGraph(GraphAdjList &GL, const MGraph& G)
{
	GL.numVertexes = G.numVertexes;			//复制顶点数
	GL.numEdges = G.numEdges;				//复制边数
	GL.adjlist.resize(GL.numVertexes);		//设置顶点数组的大小

	for (int i = 0; i < GL.numVertexes; ++i) {
		for (int j = GL.numVertexes - 1; j >= 0; --j) {		//从后往前遍历每一行,保证 Vj 在链表中的相对顺序
			if (G.arcs[i][j] < N && G.arcs[i][j] != 0) {	//如果 Vi 至 Vj 有边
				EdgeNode* e = new EdgeNode;
				e->adjvex = j;
				e->weight = G.arcs[i][j];
				e->next = GL.adjlist[i].firstEdge;		//利用头插法将 e 插入 Vi 的邻接链表
				GL.adjlist[i].firstEdge = e;

				++GL.adjlist[i].od;		//Vi的出度增加
				++GL.adjlist[j].id;		//Vj的入度增加
			}
		}
		GL.adjlist[i].data = G.vexs[i]; //复制顶点的值
	}
}

/*打印邻接表*/
void ShowAdjList(const GraphAdjList& GL)
{
	std::cout << std::endl << "顶点总数: " << GL.numVertexes << "  边总数: " << GL.numEdges << std::endl;
	for (int i = 0; i < GL.numVertexes; ++i) {
		if (i < 10)
			std::cout << " V" << i;
		else
			std::cout << "V" << i;
		std::cout << "(" << GL.adjlist[i].data << ") OD:" << GL.adjlist[i].od << " ID:" << GL.adjlist[i].id << "  FG";
		auto p = GL.adjlist[i].firstEdge;
		while (p) {
			std::cout << " -> V" << p->adjvex << "[" << p->weight << "]";
			p = p->next;
		}
		std::cout << std::endl;
	}
	std::cout << std::endl;
}

/*  通过邻接矩阵建立边集数组  *******************************************************************************************/

/*对边集数组Edge结构的定义*/
typedef struct {
	int begin;
	int end;
	int weight;
}EdgeArray;

/*通过邻接矩阵建立边集数组*/
void CreateEdgArrByGrraph(const MGraph& G, vector<EdgeArray>& edges)
{
	edges.resize(G.numEdges);	//设置边集数组大小

	/*开始循环*/
	for (int i = 0, k = 0; i < G.numVertexes; ++i) {
		for (int j = i + 1; j < G.numVertexes; ++j) {
			if (G.arcs[i][j] < myINFINITY) {
				edges[k].begin = i;
				edges[k].end = j;
				edges[k].weight = G.arcs[i][j];
				++k;
			}
		}
	}
	std::sort(edges.begin(), edges.end(), [](const EdgeArray& a, const EdgeArray& b) {
		return (a.weight < b.weight);
	});
}

/*打印边集数组*/
void ShowEdgArr(const vector<EdgeArray>& edges) {
	std::cout << "           begin   end  weight\n";
	for (int i = 0; i < edges.size(); ++i) {
		std::cout << "edges[" << right << setw(2) << i << "]" << setw(5) << edges[i].begin
			<< setw(7) << edges[i].end << setw(7) << edges[i].weight << std::endl;
	}
}

#endif

猜你喜欢

转载自blog.csdn.net/qq_40843865/article/details/89221809