From d3ea84ba977be6e537927fea7440be1c0cf709f6 Mon Sep 17 00:00:00 2001 From: "Leo.Cai" <2454787428@qq.com> Date: Sat, 11 Feb 2023 18:07:01 +0800 Subject: [PATCH] Add graph c++ code (#357) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * add c++ graph code * fix the header * delete the header wrongly auto added by editor * fix for format * fix code style * fix code style * fix graph_adjacency_list.cpp,alter 构造函数 to 构造方法 * update the markdown * add deconstructor * remove the deconstructor * Update graph_adjacency_matrix.cpp * Update graph_adjacency_list.cpp --------- Co-authored-by: Yudong Jin --- .../chapter_graph/graph_adjacency_list.cpp | 129 ++++++++++++++++++ .../chapter_graph/graph_adjacency_matrix.cpp | 126 +++++++++++++++++ 2 files changed, 255 insertions(+) create mode 100644 codes/cpp/chapter_graph/graph_adjacency_list.cpp create mode 100644 codes/cpp/chapter_graph/graph_adjacency_matrix.cpp diff --git a/codes/cpp/chapter_graph/graph_adjacency_list.cpp b/codes/cpp/chapter_graph/graph_adjacency_list.cpp new file mode 100644 index 000000000..a7f249d70 --- /dev/null +++ b/codes/cpp/chapter_graph/graph_adjacency_list.cpp @@ -0,0 +1,129 @@ +/** + * File: graph_adjacency_list.cpp + * Created Time: 2023-02-09 + * Author: what-is-me (whatisme@outlook.jp) + */ + +#include "../include/include.hpp" + +/* 顶点类 */ +struct Vertex { + int val; + Vertex(int val) : val(val) {} +}; + +/* 基于邻接表实现的无向图类 */ +class GraphAdjList { + // 请注意,vertices 和 adjList 中存储的都是 Vertex 对象 + unordered_map> adjList; // 邻接表(使用哈希表实现) + +public: + /* 构造方法 */ + GraphAdjList(const vector>& edges) { + // 添加所有顶点和边 + for (const vector& edge : edges) { + addVertex(edge[0]); + addVertex(edge[1]); + addEdge(edge[0], edge[1]); + } + } + + /* 获取顶点数量 */ + int size() { return adjList.size(); } + + /* 添加边 */ + void addEdge(Vertex* vet1, Vertex* vet2) { + if (!adjList.count(vet1) || !adjList.count(vet2) || vet1 == vet2) + throw invalid_argument("不存在顶点"); + // 添加边 vet1 - vet2 + adjList[vet1].insert(vet2); + adjList[vet2].insert(vet1); + } + + /* 删除边 */ + void removeEdge(Vertex* vet1, Vertex* vet2) { + if (!adjList.count(vet1) || !adjList.count(vet2) || vet1 == vet2) + throw invalid_argument("不存在顶点"); + // 删除边 vet1 - vet2 + adjList[vet1].erase(vet2); + adjList[vet2].erase(vet1); + } + + /* 添加顶点 */ + void addVertex(Vertex* vet) { + if (adjList.count(vet)) return; + // 在邻接表中添加一个新链表(即 HashSet) + adjList[vet] = unordered_set(); + } + + /* 删除顶点 */ + void removeVertex(Vertex* vet) { + if (!adjList.count(vet)) + throw invalid_argument("不存在顶点"); + // 在邻接表中删除顶点 vet 对应的链表(即 HashSet) + adjList.erase(vet); + // 遍历其它顶点的链表(即 HashSet),删除所有包含 vet 的边 + for (auto& [key, set_] : adjList) { + set_.erase(vet); + } + } + + /* 打印邻接表 */ + void print() { + cout << "邻接表 =" << endl; + for (auto& [key, value] : adjList) { + vector tmp; + for (Vertex* vertex : value) + tmp.push_back(vertex->val); + cout << key->val << ": "; + PrintUtil::printVector(tmp); + } + } +}; + + +/* Driver Code */ +int main() { + /* 初始化无向图 */ + Vertex *v0 = new Vertex(1), + *v1 = new Vertex(3), + *v2 = new Vertex(2), + *v3 = new Vertex(5), + *v4 = new Vertex(4); + vector> edges = {{v0, v1}, {v1, v2}, {v2, v3}, {v0, v3}, {v2, v4}, {v3, v4}}; + GraphAdjList graph(edges); + cout << "\n初始化后,图为" << endl; + graph.print(); + + /* 添加边 */ + // 顶点 1, 2 即 v0, v2 + graph.addEdge(v0, v2); + cout << "\n添加边 1-2 后,图为" << endl; + graph.print(); + + /* 删除边 */ + // 顶点 1, 3 即 v0, v1 + graph.removeEdge(v0, v1); + cout << "\n删除边 1-3 后,图为" << endl; + graph.print(); + + /* 添加顶点 */ + Vertex* v5 = new Vertex(6); + graph.addVertex(v5); + cout << "\n添加顶点 6 后,图为" << endl; + graph.print(); + + /* 删除顶点 */ + // 顶点 3 即 v1 + graph.removeVertex(v1); + cout << "\n删除顶点 3 后,图为" << endl; + graph.print(); + + /* 释放内存 */ + delete v0; + delete v1; + delete v2; + delete v3; + delete v4; + delete v5; +} diff --git a/codes/cpp/chapter_graph/graph_adjacency_matrix.cpp b/codes/cpp/chapter_graph/graph_adjacency_matrix.cpp new file mode 100644 index 000000000..b188cdda6 --- /dev/null +++ b/codes/cpp/chapter_graph/graph_adjacency_matrix.cpp @@ -0,0 +1,126 @@ +/** + * File: graph_adjacency_matrix.cpp + * Created Time: 2023-02-09 + * Author: what-is-me (whatisme@outlook.jp) + */ + +#include "../include/include.hpp" + +/* 基于邻接矩阵实现的无向图类 */ +class GraphAdjMat { + vector vertices; // 顶点列表,元素代表“顶点值”,索引代表“顶点索引” + vector> adjMat; // 邻接矩阵,行列索引对应“顶点索引” + +public: + /* 构造方法 */ + GraphAdjMat(const vector& vertices, const vector>& edges) { + // 添加顶点 + for (int val : vertices) { + addVertex(val); + } + // 添加边 + // 请注意,edges 元素代表顶点索引,即对应 vertices 元素索引 + for (const vector& edge : edges) { + addEdge(edge[0], edge[1]); + } + } + + /* 获取顶点数量 */ + int size() const { + return vertices.size(); + } + + /* 添加顶点 */ + void addVertex(int val) { + int n = size(); + // 向顶点列表中添加新顶点的值 + vertices.push_back(val); + // 在邻接矩阵中添加一行 + adjMat.emplace_back(n, 0); + // 在邻接矩阵中添加一列 + for (vector& row : adjMat) { + row.push_back(0); + } + } + + /* 删除顶点 */ + void removeVertex(int index) { + if (index >= size()) { + throw out_of_range("顶点不存在"); + } + // 在顶点列表中移除索引 index 的顶点 + vertices.erase(vertices.begin() + index); + // 在邻接矩阵中删除索引 index 的行 + adjMat.erase(adjMat.begin() + index); + // 在邻接矩阵中删除索引 index 的列 + for (vector& row : adjMat) { + row.erase(row.begin() + index); + } + } + + /* 添加边 */ + // 参数 i, j 对应 vertices 元素索引 + void addEdge(int i, int j) { + // 索引越界与相等处理 + if (i < 0 || j < 0 || i >= size() || j >= size() || i == j) { + throw out_of_range("顶点不存在"); + } + // 在无向图中,邻接矩阵沿主对角线对称,即满足 (i, j) == (j, i) + adjMat[i][j] = 1; + adjMat[j][i] = 1; + } + + /* 删除边 */ + // 参数 i, j 对应 vertices 元素索引 + void removeEdge(int i, int j) { + // 索引越界与相等处理 + if (i < 0 || j < 0 || i >= size() || j >= size() || i == j) { + throw out_of_range("顶点不存在"); + } + adjMat[i][j] = 0; + adjMat[j][i] = 0; + } + + /* 打印邻接矩阵 */ + void print() { + cout << "顶点列表 = "; + PrintUtil::printVector(vertices); + cout << "邻接矩阵 =" << endl; + PrintUtil::printVectorMatrix(adjMat); + } +}; + + +/* Driver Code */ +int main() { + /* 初始化无向图 */ + // 请注意,edges 元素代表顶点索引,即对应 vertices 元素索引 + vector vertices = {1, 3, 2, 5, 4}; + vector> edges = {{0, 1}, {0, 2}, {1, 2}, {2, 3}, {0, 3}, {2, 4}, {3, 4}}; + GraphAdjMat graph(vertices, edges); + cout << "\n初始化后,图为" << endl; + graph.print(); + + /* 添加边 */ + // 顶点 1, 2 的索引分别为 0, 2 + graph.addEdge(0, 2); + cout << "\n添加边 1-2 后,图为" << endl; + graph.print(); + + /* 删除边 */ + // 顶点 1, 3 的索引分别为 0, 1 + graph.removeEdge(0, 1); + cout << "\n删除边 1-3 后,图为" << endl; + graph.print(); + + /* 添加顶点 */ + graph.addVertex(6); + cout << "\n添加顶点 6 后,图为" << endl; + graph.print(); + + /* 删除顶点 */ + // 顶点 3 的索引为 1 + graph.removeVertex(1); + cout << "\n删除顶点 3 后,图为" << endl; + graph.print(); +}