本篇只是简单的实现,具体图的介绍请看其他博文。
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_pointCount | int | 私有 | 点的个数 |
2.2.方法
方法名 | 返回类型 | 参数 | 属性 | 说明 |
---|---|---|---|---|
Graph() | - | int pointCount | 公有 | 传点数构造 |
Graph() | - | const Graph& G | 公有 | 拷贝构造 |
~Graph() | - | - | 公有 | 析构函数 |
operator = () | Graph& | const Graph& G | 公有 | =运算符重载 |
init() | void | int pointCount | 公有 | 初始化 |
getPointCount() | int | - | 公有 | 返回图的点数 |
getEdgeCount() | int | - | 公有 | 返回边的数量 |
setPoint() | bool | int 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.总结
上面只是一种实现方式,往后再写其他的实现方式。