第96篇 C++数据结构(六)图-领接矩阵实现


本篇只是简单的实现,具体图的介绍请看其他博文。

1.图的简介

图(Graph)是由顶点的有穷非空集合 V ( G ) V(G) V(G)和顶点之间边的集合 E ( G ) E(G) E(G)组成,通常表示为: G = ( V , E ) G=(V,E) G=(V,E),其中, G G G表示个图, V V V是图 G G G中顶点的集合, E E E是图 G G G中边的集合。若 V = { v 1 , v 2 , . . . , v n } V= {v_1, v_2,…,v_n} V={v1​,v2​,…,vn​},则用 ∣ V ∣ |V| ∣V∣表示图 G G G中顶点的个数,也称图 G G G的阶, E = { ( u , v ) ∣ u ∈ V , v ∈ V } E= {(u, v) |u∈V, v∈V} E={(u,v)∣u∈V,v∈V},用 ∣ E ∣ |E| ∣E∣表示图 G G G中边的条数。

1.1.大佬文章链接

数据结构:图(Graph)【详解】
这篇文章非常详细。

2.实现

2.1.变量

变量名称类型属性说明
m_pointList_PointType*私有图中点的集合
m_collarMatrix_EdgeDataType**私有图的领接矩阵
m_pointCountint私有点的个数

2.2.方法

方法名返回类型参数属性说明
Graph()-int pointCount公有传点数构造
Graph()-const Graph& G公有拷贝构造
~Graph()--公有析构函数
operator = ()Graph&const Graph& G公有=运算符重载
init()voidint pointCount公有初始化
getPointCount()int-公有返回图的点数
getEdgeCount()int-公有返回边的数量
setPoint()boolint pointIndex, _PointType pointName公有设置点的名称
addPoint()bool_PointType pointName公有添加点
removePoint()bool_PointType pointName公有删除点
addEdge()bool_PointType firstPoint, _PointType secondePoint, _EdgeDataType edgeValue公有添加边
setEdge)bool(_PointType firstPoint, _PointType secondePoint, _EdgeDataType edgeValue公有设置边
removeEdge()bool_PointType firstPoint, _PointType secondePoint公有删除边
printPoint()void-公有打印点
printGraph()void-公有打印图
DFS()void-公有深度遍历(提供外部接口)
BFS()void-公有广度优先遍历
DFS()void_EdgeDataType** collarMatrix, int currentPointIndex, bool* isVisit保护深度优先遍历
clear()void-保护清空图(释放内存)

3.测试

3.1.测试代码

只是简单的测试了一下。

#include <iostream>

#include "Graph.h"

int main()
{
	Graph<int, char> graph(8);
	for (int i = 0; i < graph.getPointCount(); i++)
	{
		graph.setPoint(i, 'a' + i);
	}

	std::cout << "构造一个有8个点的图,点的名称为:abcdefgh" << std::endl;
	graph.printPoint();
	graph.printGraph();

	std::cout << "添加7条边:" << std::endl;
	graph.addEdge('a', 'b', 1);
	graph.addEdge('a', 'c', 1);
	graph.addEdge('b', 'd', 1);
	graph.addEdge('b', 'e', 1);
	graph.addEdge('e', 'h', 1);
	graph.addEdge('c', 'f', 1);
	graph.addEdge('c', 'g', 1);
	graph.printPoint();
	graph.printGraph();

	std::cout << "深度优先搜索:" << std::endl;
	graph.DFS();
	std::cout << std::endl;

	std::cout << "广度优先搜索:" << std::endl;
	graph.BFS();
	std::cout << std::endl;

	std::cout << "边数:" << graph.getEdgeCount() << std::endl;
	std::cout << "点数:" << graph.getPointCount() << std::endl;

	std::cout << "添加一个s点:" << std::endl;
	graph.addPoint('s');
	graph.printPoint();
	graph.printGraph();

	std::cout << "添加两条边:as, ds" << std::endl;
	graph.addEdge('a', 's', 1);
	graph.addEdge('d', 's', 1);
	graph.printPoint();
	graph.printGraph();

	std::cout << "删除一条边:cf" << std::endl;
	graph.removeEdge('c', 'f');
	graph.printPoint();
	graph.printGraph();

	std::cout << "删除点f:" << std::endl;
	graph.removePoint('f');
	graph.printPoint();
	graph.printGraph();

	return 0;
}

3.2.输出结果

构造一个有8个点的图,点的名称为:abcdefgh
[a, b, c, d, e, f, g, h]
[0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0]
添加7条边:
[a, b, c, d, e, f, g, h]
[0, 1, 1, 0, 0, 0, 0, 0]
[1, 0, 0, 1, 1, 0, 0, 0]
[1, 0, 0, 0, 0, 1, 1, 0]
[0, 1, 0, 0, 0, 0, 0, 0]
[0, 1, 0, 0, 0, 0, 0, 1]
[0, 0, 1, 0, 0, 0, 0, 0]
[0, 0, 1, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 1, 0, 0, 0]
深度优先搜索:
a, b, d, e, h, c, f, g,
广度优先搜索:
a, b, c, d, e, f, g, h,
边数:7
点数:8
添加一个s点:
[a, b, c, d, e, f, g, h, s]
[0, 1, 1, 0, 0, 0, 0, 0, 0]
[1, 0, 0, 1, 1, 0, 0, 0, 0]
[1, 0, 0, 0, 0, 1, 1, 0, 0]
[0, 1, 0, 0, 0, 0, 0, 0, 0]
[0, 1, 0, 0, 0, 0, 0, 1, 0]
[0, 0, 1, 0, 0, 0, 0, 0, 0]
[0, 0, 1, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 1, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0]
添加两条边:as, ds
[a, b, c, d, e, f, g, h, s]
[0, 1, 1, 0, 0, 0, 0, 0, 1]
[1, 0, 0, 1, 1, 0, 0, 0, 0]
[1, 0, 0, 0, 0, 1, 1, 0, 0]
[0, 1, 0, 0, 0, 0, 0, 0, 1]
[0, 1, 0, 0, 0, 0, 0, 1, 0]
[0, 0, 1, 0, 0, 0, 0, 0, 0]
[0, 0, 1, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 1, 0, 0, 0, 0]
[1, 0, 0, 1, 0, 0, 0, 0, 0]
删除一条边:cf
[a, b, c, d, e, f, g, h, s]
[0, 1, 1, 0, 0, 0, 0, 0, 1]
[1, 0, 0, 1, 1, 0, 0, 0, 0]
[1, 0, 0, 0, 0, 0, 1, 0, 0]
[0, 1, 0, 0, 0, 0, 0, 0, 1]
[0, 1, 0, 0, 0, 0, 0, 1, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 1, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 1, 0, 0, 0, 0]
[1, 0, 0, 1, 0, 0, 0, 0, 0]
删除点f:
[a, b, c, d, e, g, h, s]
[0, 1, 1, 0, 0, 0, 0, 1]
[1, 0, 0, 1, 1, 0, 0, 0]
[1, 0, 0, 0, 0, 1, 0, 0]
[0, 1, 0, 0, 0, 0, 0, 1]
[0, 1, 0, 0, 0, 0, 1, 0]
[0, 0, 1, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 1, 0, 0, 0]
[1, 0, 0, 1, 0, 0, 0, 0]

4.实现代码

#pragma once
#ifndef _GRAPH_h_
#define _GRAPH_H_

#include <iostream>
#include <queue>

template <typename _EdgeDataType, typename _PointType>
class Graph
{
public:
	Graph(int pointCount)
	{
		init(pointCount);

		for (int i = 0; i < m_pointCount; i++)
		{
			m_pointList[i] = _PointType();
		}

		for (int i = 0; i < m_pointCount; i++)
		{
			for (int j = 0; j < m_pointCount ; j++)
			{
				m_collarMatrix[i][j] = _EdgeDataType();
			}
		}
	}

	Graph(const Graph& G)
	{
		init(G.m_pointCount);

		for (int i = 0; i < m_pointCount; i++)
		{
			m_pointList[i] = G.m_pointList[i];
		}

		for (int i = 0; i < m_pointCount; i++)
		{
			for (int j = 0; j < m_pointCount; j++)
			{
				m_collarMatrix[i][j] = G.m_collarMatrix[i][j];
			}
		}
	}

	~Graph()
	{
		clear();
	}

	Graph& operator = (const Graph& G)
	{
		if (m_pointCount != 0)
		{
			clear();
		}

		init(G.m_pointCount);

		for (int i = 0; i < m_pointCount; i++)
		{
			m_pointList[i] = G.m_pointList[i];
		}

		for (int i = 0; i < m_pointCount; i++)
		{
			for (int j = 0; j < m_pointCount; j++)
			{
				m_collarMatrix[i][j] = G.m_collarMatrix[i][j];
			}
		}

		return *this;
	}

	void init(int pointCount)
	{
		if (pointCount <= 0)
		{
			m_collarMatrix = nullptr;
			m_pointList = nullptr;
			m_pointCount = 0;
		}
		else
		{
			m_pointList = new _PointType[pointCount];

			m_collarMatrix = new _EdgeDataType * [pointCount];
			for (int i = 0; i < pointCount; i++)
			{
				m_collarMatrix[i] = new _EdgeDataType[pointCount];
			}

			m_pointCount = pointCount;
		}
	}

	int getPointCount() const
	{
		return m_pointCount;
	}

	int getEdgeCount() const
	{
		int edgeCount(0);
		for (int i = 0; i < m_pointCount; i++)
		{
			for (int j = i + 1; j < m_pointCount; j++)
			{
				if (m_collarMatrix[i][j] != _EdgeDataType())
				{
					edgeCount++;
				}
			}
		}

		return edgeCount;
	}

	bool setPoint(int pointIndex, _PointType pointName)
	{
		if (pointIndex < 0 || pointIndex >= m_pointCount)
		{
			return false;
		}

		for (int i = 0; i < m_pointCount; i++)
		{
			if (m_pointList[i] == pointName)
			{
				return false;
			}
		}

		m_pointList[pointIndex] = pointName;

		return true;
	}

	bool addPoint(_PointType pointName)
	{
		int pointCount = m_pointCount + 1;

		for (int i = 0; i < m_pointCount; i++)
		{
			if (m_pointList[i] == pointName)
			{
				return false;
			}
		}

		_PointType* pointList = new _PointType[m_pointCount + 1];
		for (int i = 0; i < m_pointCount; i++)
		{
			pointList[i] = m_pointList[i];
		}
		pointList[m_pointCount] = pointName;

		_EdgeDataType** collarMatrix = new _EdgeDataType*[m_pointCount + 1];
		for (int i = 0; i < m_pointCount + 1; i++)
		{
			collarMatrix[i] = new _EdgeDataType[m_pointCount + 1];
		}

		for (int i = 0; i < m_pointCount + 1; i++)
		{
			for (int j = 0; j < m_pointCount + 1; j++)
			{
				if (i < m_pointCount && j < m_pointCount)
				{
					collarMatrix[i][j] = m_collarMatrix[i][j];
				}
				else
				{
					collarMatrix[i][j] = _EdgeDataType();
				}
			}
		}

		clear();

		m_pointCount = pointCount;
		m_pointList = pointList;
		m_collarMatrix = collarMatrix;

		return true;
	}

	bool removePoint(_PointType pointName)
	{
		int pointCount = m_pointCount - 1;

		int removeIndex = 0;
		for (; removeIndex < m_pointCount; removeIndex++)
		{
			if (m_pointList[removeIndex] == pointName)
			{
				break;
			}
		}
		if (removeIndex == m_pointCount)
		{
			return false;
		}

		_PointType* pointList = new _PointType[m_pointCount - 1];
		for (int i = 0; i < m_pointCount - 1; i++)
		{
			if (i < removeIndex)
			{
				pointList[i] = m_pointList[i];
			}
			else
			{
				pointList[i] = m_pointList[i + 1];
			}
		}

		_EdgeDataType** collarMatrix = new _EdgeDataType * [m_pointCount - 1];
		for (int i = 0; i < m_pointCount - 1; i++)
		{
			collarMatrix[i] = new _EdgeDataType[m_pointCount - 1];
		}

		for (int i = 0; i < m_pointCount - 1; i++)
		{
			for (int j = 0; j < m_pointCount - 1; j++)
			{
				if (i < removeIndex && j < removeIndex)
				{
					collarMatrix[i][j] = m_collarMatrix[i][j];
				}
				else if (i < removeIndex && j >= removeIndex)
				{
					collarMatrix[i][j] = m_collarMatrix[i][j + 1];
				}
				else if (i >= removeIndex && j < removeIndex)
				{
					collarMatrix[i][j] = m_collarMatrix[i + 1][j];
				}
				else
				{
					collarMatrix[i][j] = m_collarMatrix[i + 1][j + 1];
				}
			}
		}

		clear();

		m_pointCount = pointCount;
		m_pointList = pointList;
		m_collarMatrix = collarMatrix;

		return true;
	}

	bool addEdge(_PointType firstPoint, _PointType secondePoint, _EdgeDataType edgeValue)
	{
		if (edgeValue == _EdgeDataType() || firstPoint == secondePoint)
		{
			return false;
		}

		int firstPointIndex = 0;
		for (; firstPointIndex < m_pointCount; firstPointIndex++)
		{
			if (m_pointList[firstPointIndex] == firstPoint)
			{
				break;
			}
		}
		if (firstPointIndex == m_pointCount)
		{
			return false;
		}

		int secondPointIndex = 0;
		for (; secondPointIndex < m_pointCount; secondPointIndex++)
		{
			if (m_pointList[secondPointIndex] == secondePoint)
			{
				break;
			}
		}
		if (secondPointIndex == m_pointCount)
		{
			return false;
		}

		m_collarMatrix[firstPointIndex][secondPointIndex] = edgeValue;
		m_collarMatrix[secondPointIndex][firstPointIndex] = edgeValue;

		return true;
	}

	bool setEdge(_PointType firstPoint, _PointType secondePoint, _EdgeDataType edgeValue)
	{
		if (edgeValue == _EdgeDataType())
		{
			return false;
		}

		int firstPointIndex = 0;
		for (; firstPointIndex < m_pointCount; firstPointIndex++)
		{
			if (m_pointList[firstPointIndex] == firstPoint)
			{
				break;
			}
		}
		if (firstPointIndex == m_pointCount)
		{
			return false;
		}

		int secondPointIndex = 0;
		for (; secondPointIndex < m_pointCount; secondPointIndex++)
		{
			if (m_pointList[secondPointIndex] == secondePoint)
			{
				break;
			}
		}
		if (secondPointIndex == m_pointCount)
		{
			return false;
		}

		m_collarMatrix[firstPointIndex][secondPointIndex] = edgeValue;
		m_collarMatrix[secondPointIndex][firstPointIndex] = edgeValue;

		return true;
	}

	bool removeEdge(_PointType firstPoint, _PointType secondePoint)
	{
		int firstPointIndex = 0;
		for (; firstPointIndex < m_pointCount; firstPointIndex++)
		{
			if (m_pointList[firstPointIndex] == firstPoint)
			{
				break;
			}
		}
		if (firstPointIndex == m_pointCount)
		{
			return false;
		}

		int secondPointIndex = 0;
		for (; secondPointIndex < m_pointCount; secondPointIndex++)
		{
			if (m_pointList[secondPointIndex] == secondePoint)
			{
				break;
			}
		}
		if (secondPointIndex == m_pointCount)
		{
			return false;
		}

		m_collarMatrix[firstPointIndex][secondPointIndex] = _EdgeDataType();
		m_collarMatrix[secondPointIndex][firstPointIndex] = _EdgeDataType();

		return true;
	}

	void printPoint() const
	{
		if (m_pointCount == 0)
		{
			return;
		}

		std::cout << "[";
		for (int j = 0; j < m_pointCount - 1; j++)
		{
			std::cout << m_pointList[j] << ", ";
		}
		std::cout << m_pointList[m_pointCount - 1] << "]" << std::endl;
	}

	void printGraph() const
	{
		for (int i = 0; i < m_pointCount; i++)
		{
			std::cout << "[";
			for (int j = 0; j < m_pointCount - 1; j++)
			{
				std::cout << m_collarMatrix[i][j] << ", ";
			}
			std::cout << m_collarMatrix[i][m_pointCount - 1] << "]" << std::endl;
		}
	}

	void DFS()
	{
		if (m_pointCount <= 0)
		{
			return;
		}

		bool* isVisit = new bool[m_pointCount];
		for (int i = 0; i < m_pointCount; i++)
		{
			isVisit[i] = false;
		}

		for (int i = 0; i < m_pointCount; i++)
		{
			if (!isVisit[i])
			{
				DFS(m_collarMatrix, i, isVisit);
			}
		}
		
		delete[]isVisit;
	}

	void BFS() {
		if (m_pointCount <= 0)
		{
			return;
		}

		bool* isVisit = new bool[m_pointCount];
		for (int i = 0; i < m_pointCount; i++)
		{
			isVisit[i] = false;
		}

		std::queue<int> pointQueue;
		for (int currentPointIndex = 0; currentPointIndex < m_pointCount; currentPointIndex++) {
			if (!isVisit[currentPointIndex]) {
				isVisit[currentPointIndex] = true;
				std::cout << m_pointList[currentPointIndex] << ", ";

				pointQueue.push(currentPointIndex);

				while (!pointQueue.empty()) {
					int currentIndex = pointQueue.front();
					pointQueue.pop();

					for (int j = 0; j < m_pointCount;j++) {
						if (m_collarMatrix[currentIndex][j] != _EdgeDataType() && !isVisit[j]) {
							std::cout << m_pointList[j] << ", ";
							isVisit[j] = true;
							pointQueue.push(j);
						}
					}
				}
			}
		}
	}

protected:
	void DFS(_EdgeDataType** collarMatrix, int currentPointIndex, bool* isVisit)
	{
		isVisit[currentPointIndex] = true;
		std::cout << m_pointList[currentPointIndex] << ", ";
		for (int j = 0; j < m_pointCount; j++)
		{
			if (collarMatrix[currentPointIndex][j] != _EdgeDataType() && !isVisit[j])
			{
				DFS(collarMatrix, j, isVisit);
			}
		}
	}

	void clear()
	{
		if (m_pointList != nullptr)
		{
			delete[]m_pointList;
			m_pointList = nullptr;
		}

		if (m_collarMatrix != nullptr)
		{
			for (int i = 0; i < m_pointCount; i++)
			{
				delete[]m_collarMatrix[i];
				m_collarMatrix[i] = nullptr;
			}

			delete[]m_collarMatrix;
			m_collarMatrix = nullptr;
		}

		m_pointCount = 0;
	}

private:
	_PointType* m_pointList;
	_EdgeDataType** m_collarMatrix;
	int m_pointCount;
};

#endif // !_GRAPH_H_

5.总结

上面只是一种实现方式,往后再写其他的实现方式。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
要创建一个有向并使用邻矩阵表示,需要以下几个步骤: 1. 定义的大小:的大小指的是中节点的数量。您可以使用一个整数n来表示。 2. 创建邻矩阵:邻矩阵是一个n x n的矩阵,其中每个元素代表节点间的连通性。如果节点i到节点j有一条有向边,则矩阵中第i行第j列的元素为1。否则,该元素为0。 3. 初始化邻矩阵:将邻矩阵中所有元素初始化为0。 4. 添加边:对于每个有向边(i, j),将邻矩阵中第i行第j列的元素设置为1。 下面是一个使用C++实现矩阵的有向的示例代码: ```c++ #include <iostream> using namespace std; const int MAXN = 100; // 定义的最大节点数 int n; // 的节点数量 int graph[MAXN][MAXN]; // 邻矩阵 int main() { // 输入节点数量 cout << "请输入节点数量:"; cin >> n; // 初始化邻矩阵 for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { graph[i][j] = 0; } } // 添加边 int m; // 边的数量 cout << "请输入边的数量:"; cin >> m; cout << "请输入每条边的起点和终点(用空格分隔):" << endl; for (int i = 0; i < m; i++) { int u, v; // 边的起点和终点 cin >> u >> v; graph[u][v] = 1; } // 输出邻矩阵 cout << "邻矩阵为:" << endl; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { cout << graph[i][j] << " "; } cout << endl; } return 0; } ``` 这段代码可以让用户输入节点数量和边的数量,并根据用户输入构建有向的邻矩阵,并将其输出到屏幕上。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大唐不良猿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值