以下是后文用到的 “__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