2020年9月25日 周六 天气晴 【不悲叹过去,不荒废现在,不惧怕未来】
本文目录
1. 引言
用C++实现了简单的图类,实现了从文件(输入格式见下)进行图的创建,并保存为邻接矩阵或邻接表,和图的打印、遍历(深度优先遍历和广度优先遍历)等功能。代码是用VS2019实现的,每个函数的功能都添加了一定注释,完整工程放在了我的github上,有需要的也可以自取。
github地址:https://github.com/March225/Data-structure-implemented-by-Cpp
图输入的格式
//文件可以加注释行,注释以//开始,且必须顶头开始,不能有空格
//文件不能有空行
//Graph为图标志,否则判定格式不对
//标志行后,第一行为图的类型。UDG--无向图;UDN--无向网;DG--有向图;DN--有向网
//标志行后,第二行为顶点元素
//顶点行以下图的边或弧。用顶点表示,第一列以顶点编号排列;第二列为邻接点;在网中增加一列表示权值。
//此图为一个有6个顶点、10条边、2个连通分量的非连通有向图。
Graph
DG
//下面为顶点列表,对应的编号为1,2,3,4,...
a b c d e f
//以下为邻接点(边)信息
a b
a d
c b
c e
d b
d e
e a
e b
f c
f e
2. 主文件——main.cpp
/**
* @Copyright (C) 2020 March. All rights reserved.
* @license GNU General Public License (GPL)
* @author March
* @email 345916208@qq.com
* @file main.cpp
* @brief 图的C++实现主文件
* @version 1.0
* @date 2020-09-23
*/
#include "stdafx.h"
#include "graph.h"
int main() {
// 文件存放路径(按照需求进行修改)
string fileName = "E:\\Program Files (x86)\\Microsoft Visual Studio\\workplace\\Graph\\grpData\\udg8.grp";
Graph* g = new Graph();
g->createAdjMatrixGraph(fileName); // 由图的邻接矩阵创建图
g->printAdjMatrixGraph(); // 打印图的类型、顶点和邻接矩阵
g->createAdjListGraph(fileName); // 由图的邻接表创建图
g->printAdjListGraph(); // 打印图的类型、顶点和邻接表
g->DFSAdjMatTraverse(); // 邻接矩阵的深度优先遍历
g->DFSAdjListTraverse(); // 邻接表的深度优先遍历
g->BFSAdjMatTraverse(); // 邻接矩阵的广度优先遍历
g->BFSAdjListTraverse(); // 邻接表的广度优先遍历
delete g;
return 0;
}
3. 图类 .h文件——graph.h
#pragma once
#include "stdafx.h"
/**
* @brief 创建一个graph类
*/
class Graph {
private:
VertexType* vexs_; // 顶点数组
EdgeType** arc_; // 邻接矩阵数组
int nVertexes_, nEdges_; // 图中当前的顶点数和边数
GraphKind graphType_; // 图的类型
VertexNode* adjList_; // 存放顶点表结点的数组
bool* visited_; // 访问标志的数组
public:
Graph(); // 构造函数
~Graph(); // 析构函数
bool createAdjMatrixGraph(string fileName); // 由图的邻接矩阵创建图
bool createAdjListGraph(string fileName); // 由图的邻接表创建图
void strTrim(string& s); // 删除字符串s左边和右边的空格
void printAdjMatrixGraph(); // 打印图的类型、顶点和邻接矩阵
void printAdjListGraph(); // 打印图的类型、顶点和邻接表
void DFSAdjMatTraverse(); // 邻接矩阵的深度优先遍历
void DFSAdjListTraverse(); // 邻接表的深度优先遍历
void BFSAdjMatTraverse(); // 邻接矩阵的广度优先遍历
void BFSAdjListTraverse(); // 邻接表的广度优先遍历
protected:
void DFSAdjMat(int i); // 邻接矩阵的深度优先递归算法
void DFSAdjList(int i); // 邻接表的深度优先递归算法
};
4. 图类 .cpp文件——graph.cpp
#include "graph.h"
// 构造函数
Graph::Graph() : nVertexes_(0), nEdges_(0), graphType_(GraphKind::None) {
vexs_ = new VertexType[kMAXVEX]; // 顶点数组
arc_ = new EdgeType * [kMAXVEX]; // 邻接矩阵数组
for (int i = 0; i < kMAXVEX; ++i) {
arc_[i] = new EdgeType[kMAXVEX](); // 初始化为0
}
adjList_ = new VertexNode[kMAXVEX](); // 存放顶点表结点的数组
visited_ = new bool[kMAXVEX]; // 访问标志的数组
};
// 析构函数
Graph::~Graph() {
delete[]vexs_;
for (int i = 0; i < kMAXVEX; ++i) {
delete[]arc_[i];
}
delete[]arc_;
delete[]adjList_;
};
// 删除字符串s左边和右边的空格
void Graph::strTrim(string& s) {
if (!s.empty()) {
s.erase(0, s.find_first_not_of(" "));
s.erase(s.find_last_not_of(" ") + 1);
}
}
// 由图的邻接矩阵创建图
bool Graph::createAdjMatrixGraph(string fileName) {
string str; // 存放读出一行文本的字符串
string strTemp; // 判断是否注释行
EdgeType eWeight; // 边的信息,常为边的权值
ifstream fin(fileName.c_str());
if (!fin)
{
cout << "错误:文件" << fileName << "打开失败。" << endl;
return false;
}
while (!fin.eof())
{
getline(fin, str);
strTrim(str); // 删除字符串左边和右边的空格,这是一个自定义的函数
if (str.empty()) continue; // 空行,继续读取下一行
strTemp = str.substr(0, 2);
if (strTemp == "//") continue; // 跳过注释行
else break; // 非注释行、非空行,跳出循环
}
// 循环结束,str中应该已经是图的标识Graph,判断标识是否正确
if (str.find("Graph") == string::npos)
{
cout << "错误:打开的文件格式错误!" << endl;
fin.close(); // 关闭文件
return false;
}
// 读取图的类型,跳过空行
while (!fin.eof())
{
getline(fin, str);
strTrim(str);