C++实现数据结构——图(完整清晰)

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); 
  • 1
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值