mirror of
https://github.com/krahets/hello-algo.git
synced 2025-02-02 22:43:50 +08:00
feat: Add C++ code for the graph bfs and dfs (#401)
* Add C++ code for the graph bfs and dfs * Add C++ code for the graph bfs and dfs
This commit is contained in:
parent
4f941e3d99
commit
33c797efeb
@ -1,24 +1,27 @@
|
|||||||
/**
|
/**
|
||||||
* File: graph_adjacency_list.cpp
|
* File: graph_adjacency_list.cpp
|
||||||
* Created Time: 2023-02-09
|
* Created Time: 2023-02-09
|
||||||
* Author: what-is-me (whatisme@outlook.jp)
|
* Author: what-is-me (whatisme@outlook.jp), Krahets (krahets@163.com)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "../include/include.hpp"
|
#include "../include/include.hpp"
|
||||||
|
|
||||||
/* 顶点类 */
|
|
||||||
struct Vertex {
|
|
||||||
int val;
|
|
||||||
Vertex(int val) : val(val) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
/* 基于邻接表实现的无向图类 */
|
/* 基于邻接表实现的无向图类 */
|
||||||
class GraphAdjList {
|
class GraphAdjList {
|
||||||
// 邻接表,使用哈希表来代替链表,以提升删除边、删除顶点的效率
|
|
||||||
// 请注意,adjList 中的元素是 Vertex 对象
|
|
||||||
unordered_map<Vertex*, unordered_set<Vertex*>> adjList;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
// 邻接表,key: 顶点,value:该顶点的所有邻接顶点
|
||||||
|
unordered_map<Vertex*, vector<Vertex*>> adjList;
|
||||||
|
|
||||||
|
/* 在 vector 中删除指定结点 */
|
||||||
|
void remove(vector<Vertex*> &vec, Vertex *vet) {
|
||||||
|
for (int i = 0; i < vec.size(); i++) {
|
||||||
|
if (vec[i] == vet) {
|
||||||
|
vec.erase(vec.begin() + i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* 构造方法 */
|
/* 构造方法 */
|
||||||
GraphAdjList(const vector<vector<Vertex*>>& edges) {
|
GraphAdjList(const vector<vector<Vertex*>>& edges) {
|
||||||
// 添加所有顶点和边
|
// 添加所有顶点和边
|
||||||
@ -37,8 +40,8 @@ public:
|
|||||||
if (!adjList.count(vet1) || !adjList.count(vet2) || vet1 == vet2)
|
if (!adjList.count(vet1) || !adjList.count(vet2) || vet1 == vet2)
|
||||||
throw invalid_argument("不存在顶点");
|
throw invalid_argument("不存在顶点");
|
||||||
// 添加边 vet1 - vet2
|
// 添加边 vet1 - vet2
|
||||||
adjList[vet1].insert(vet2);
|
adjList[vet1].push_back(vet2);
|
||||||
adjList[vet2].insert(vet1);
|
adjList[vet2].push_back(vet1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 删除边 */
|
/* 删除边 */
|
||||||
@ -46,15 +49,15 @@ public:
|
|||||||
if (!adjList.count(vet1) || !adjList.count(vet2) || vet1 == vet2)
|
if (!adjList.count(vet1) || !adjList.count(vet2) || vet1 == vet2)
|
||||||
throw invalid_argument("不存在顶点");
|
throw invalid_argument("不存在顶点");
|
||||||
// 删除边 vet1 - vet2
|
// 删除边 vet1 - vet2
|
||||||
adjList[vet1].erase(vet2);
|
remove(adjList[vet1], vet2);
|
||||||
adjList[vet2].erase(vet1);
|
remove(adjList[vet2], vet1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 添加顶点 */
|
/* 添加顶点 */
|
||||||
void addVertex(Vertex* vet) {
|
void addVertex(Vertex* vet) {
|
||||||
if (adjList.count(vet)) return;
|
if (adjList.count(vet)) return;
|
||||||
// 在邻接表中添加一个新链表
|
// 在邻接表中添加一个新链表
|
||||||
adjList[vet] = unordered_set<Vertex*>();
|
adjList[vet] = vector<Vertex*>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 删除顶点 */
|
/* 删除顶点 */
|
||||||
@ -64,67 +67,19 @@ public:
|
|||||||
// 在邻接表中删除顶点 vet 对应的链表
|
// 在邻接表中删除顶点 vet 对应的链表
|
||||||
adjList.erase(vet);
|
adjList.erase(vet);
|
||||||
// 遍历其它顶点的链表,删除所有包含 vet 的边
|
// 遍历其它顶点的链表,删除所有包含 vet 的边
|
||||||
for (auto& [key, set_] : adjList) {
|
for (auto& [key, vec] : adjList) {
|
||||||
set_.erase(vet);
|
remove(vec, vet);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 打印邻接表 */
|
/* 打印邻接表 */
|
||||||
void print() {
|
void print() {
|
||||||
cout << "邻接表 =" << endl;
|
cout << "邻接表 =" << endl;
|
||||||
for (auto& [key, value] : adjList) {
|
for (auto& [key, vec] : adjList) {
|
||||||
vector<int> tmp;
|
|
||||||
for (Vertex* vertex : value)
|
|
||||||
tmp.push_back(vertex->val);
|
|
||||||
cout << key->val << ": ";
|
cout << key->val << ": ";
|
||||||
PrintUtil::printVector(tmp);
|
PrintUtil::printVector(vetsToVals(vec));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// GraphAdjList 的测试样例在 graph_adjacency_list_test.cpp 文件中
|
||||||
/* 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<vector<Vertex*>> 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;
|
|
||||||
}
|
|
||||||
|
49
codes/cpp/chapter_graph/graph_adjacency_list_test.cpp
Normal file
49
codes/cpp/chapter_graph/graph_adjacency_list_test.cpp
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
/**
|
||||||
|
* File: graph_adjacency_list_test.cpp
|
||||||
|
* Created Time: 2023-02-09
|
||||||
|
* Author: what-is-me (whatisme@outlook.jp), Krahets (krahets@163.com)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "./graph_adjacency_list.cpp"
|
||||||
|
|
||||||
|
/* Driver Code */
|
||||||
|
int main() {
|
||||||
|
/* 初始化无向图 */
|
||||||
|
vector<Vertex*> v = valsToVets(vector<int> { 1, 3, 2, 5, 4 });
|
||||||
|
vector<vector<Vertex*>> edges = { { v[0], v[1] }, { v[0], v[3] }, { v[1], v[2] },
|
||||||
|
{ v[2], v[3] }, { v[2], v[4] }, { v[3], v[4] } };
|
||||||
|
GraphAdjList graph(edges);
|
||||||
|
cout << "\n初始化后,图为" << endl;
|
||||||
|
graph.print();
|
||||||
|
|
||||||
|
/* 添加边 */
|
||||||
|
// 顶点 1, 2 即 v[0], v[2]
|
||||||
|
graph.addEdge(v[0], v[2]);
|
||||||
|
cout << "\n添加边 1-2 后,图为" << endl;
|
||||||
|
graph.print();
|
||||||
|
|
||||||
|
/* 删除边 */
|
||||||
|
// 顶点 1, 3 即 v[0], v[1]
|
||||||
|
graph.removeEdge(v[0], v[1]);
|
||||||
|
cout << "\n删除边 1-3 后,图为" << endl;
|
||||||
|
graph.print();
|
||||||
|
|
||||||
|
/* 添加顶点 */
|
||||||
|
Vertex* v5 = new Vertex(6);
|
||||||
|
graph.addVertex(v5);
|
||||||
|
cout << "\n添加顶点 6 后,图为" << endl;
|
||||||
|
graph.print();
|
||||||
|
|
||||||
|
/* 删除顶点 */
|
||||||
|
// 顶点 3 即 v[1]
|
||||||
|
graph.removeVertex(v[1]);
|
||||||
|
cout << "\n删除顶点 3 后,图为" << endl;
|
||||||
|
graph.print();
|
||||||
|
|
||||||
|
// 释放内存
|
||||||
|
for (Vertex *vet : v) {
|
||||||
|
delete vet;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -8,8 +8,8 @@
|
|||||||
|
|
||||||
/* 基于邻接矩阵实现的无向图类 */
|
/* 基于邻接矩阵实现的无向图类 */
|
||||||
class GraphAdjMat {
|
class GraphAdjMat {
|
||||||
vector<int> vertices; // 顶点列表,元素代表“顶点值”,索引代表“顶点索引”
|
vector<int> vertices; // 顶点列表,元素代表“顶点值”,索引代表“顶点索引”
|
||||||
vector<vector<int>> adjMat; // 邻接矩阵,行列索引对应“顶点索引”
|
vector<vector<int>> adjMat; // 邻接矩阵,行列索引对应“顶点索引”
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/* 构造方法 */
|
/* 构造方法 */
|
||||||
@ -90,13 +90,12 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* Driver Code */
|
/* Driver Code */
|
||||||
int main() {
|
int main() {
|
||||||
/* 初始化无向图 */
|
/* 初始化无向图 */
|
||||||
// 请注意,edges 元素代表顶点索引,即对应 vertices 元素索引
|
// 请注意,edges 元素代表顶点索引,即对应 vertices 元素索引
|
||||||
vector<int> vertices = {1, 3, 2, 5, 4};
|
vector<int> vertices = { 1, 3, 2, 5, 4 };
|
||||||
vector<vector<int>> edges = {{0, 1}, {0, 2}, {1, 2}, {2, 3}, {0, 3}, {2, 4}, {3, 4}};
|
vector<vector<int>> edges = { { 0, 1 }, { 0, 3 }, { 1, 2 }, { 2, 3 }, { 2, 4 }, { 3, 4 } };
|
||||||
GraphAdjMat graph(vertices, edges);
|
GraphAdjMat graph(vertices, edges);
|
||||||
cout << "\n初始化后,图为" << endl;
|
cout << "\n初始化后,图为" << endl;
|
||||||
graph.print();
|
graph.print();
|
||||||
@ -123,4 +122,6 @@ int main() {
|
|||||||
graph.removeVertex(1);
|
graph.removeVertex(1);
|
||||||
cout << "\n删除顶点 3 后,图为" << endl;
|
cout << "\n删除顶点 3 后,图为" << endl;
|
||||||
graph.print();
|
graph.print();
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
59
codes/cpp/chapter_graph/graph_bfs.cpp
Normal file
59
codes/cpp/chapter_graph/graph_bfs.cpp
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
/**
|
||||||
|
* File: graph_bfs.cpp
|
||||||
|
* Created Time: 2023-03-02
|
||||||
|
* Author: Krahets (krahets@163.com)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../include/include.hpp"
|
||||||
|
#include "./graph_adjacency_list.cpp"
|
||||||
|
|
||||||
|
/* 广度优先遍历 BFS */
|
||||||
|
// 使用邻接表来表示图,以便获取指定顶点的所有邻接顶点
|
||||||
|
vector<Vertex*> graphBFS(GraphAdjList &graph, Vertex *startVet) {
|
||||||
|
// 顶点遍历序列
|
||||||
|
vector<Vertex*> res;
|
||||||
|
// 哈希表,用于记录已被访问过的顶点
|
||||||
|
unordered_set<Vertex*> visited = { startVet };
|
||||||
|
// 队列用于实现 BFS
|
||||||
|
queue<Vertex*> que;
|
||||||
|
que.push(startVet);
|
||||||
|
// 以顶点 vet 为起点,循环直至访问完所有顶点
|
||||||
|
while (!que.empty()) {
|
||||||
|
Vertex *vet = que.front();
|
||||||
|
que.pop(); // 队首顶点出队
|
||||||
|
res.push_back(vet); // 记录访问顶点
|
||||||
|
// 遍历该顶点的所有邻接顶点
|
||||||
|
for (auto adjVet : graph.adjList[vet]) {
|
||||||
|
if (visited.count(adjVet))
|
||||||
|
continue; // 跳过已被访问过的顶点
|
||||||
|
que.push(adjVet); // 只入队未访问的顶点
|
||||||
|
visited.emplace(adjVet); // 标记该顶点已被访问
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 返回顶点遍历序列
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Driver Code */
|
||||||
|
int main() {
|
||||||
|
/* 初始化无向图 */
|
||||||
|
vector<Vertex*> v = valsToVets({ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 });
|
||||||
|
vector<vector<Vertex*>> edges = { { v[0], v[1] }, { v[0], v[3] }, { v[1], v[2] }, { v[1], v[4] },
|
||||||
|
{ v[2], v[5] }, { v[3], v[4] }, { v[3], v[6] }, { v[4], v[5] },
|
||||||
|
{ v[4], v[7] }, { v[5], v[8] }, { v[6], v[7] }, { v[7], v[8] } };
|
||||||
|
GraphAdjList graph(edges);
|
||||||
|
cout << "\n初始化后,图为\\n";
|
||||||
|
graph.print();
|
||||||
|
|
||||||
|
/* 广度优先遍历 BFS */
|
||||||
|
vector<Vertex*> res = graphBFS(graph, v[0]);
|
||||||
|
cout << "\n广度优先遍历(BFS)顶点序列为" << endl;
|
||||||
|
PrintUtil::printVector(vetsToVals(res));
|
||||||
|
|
||||||
|
// 释放内存
|
||||||
|
for (Vertex *vet : v) {
|
||||||
|
delete vet;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
55
codes/cpp/chapter_graph/graph_dfs.cpp
Normal file
55
codes/cpp/chapter_graph/graph_dfs.cpp
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
/**
|
||||||
|
* File: graph_dfs.cpp
|
||||||
|
* Created Time: 2023-03-02
|
||||||
|
* Author: Krahets (krahets@163.com)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../include/include.hpp"
|
||||||
|
#include "./graph_adjacency_list.cpp"
|
||||||
|
|
||||||
|
/* 深度优先遍历 DFS 辅助函数 */
|
||||||
|
void dfs(GraphAdjList& graph, unordered_set<Vertex*>& visited, vector<Vertex*>& res, Vertex* vet) {
|
||||||
|
res.push_back(vet); // 记录访问顶点
|
||||||
|
visited.emplace(vet); // 标记该顶点已被访问
|
||||||
|
// 遍历该顶点的所有邻接顶点
|
||||||
|
for (Vertex* adjVet : graph.adjList[vet]) {
|
||||||
|
if (visited.count(adjVet))
|
||||||
|
continue; // 跳过已被访问过的顶点
|
||||||
|
// 递归访问邻接顶点
|
||||||
|
dfs(graph, visited, res, adjVet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 深度优先遍历 DFS */
|
||||||
|
// 使用邻接表来表示图,以便获取指定顶点的所有邻接顶点
|
||||||
|
vector<Vertex*> graphDFS(GraphAdjList& graph, Vertex* startVet) {
|
||||||
|
// 顶点遍历序列
|
||||||
|
vector<Vertex*> res;
|
||||||
|
// 哈希表,用于记录已被访问过的顶点
|
||||||
|
unordered_set<Vertex*> visited;
|
||||||
|
dfs(graph, visited, res, startVet);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Driver Code */
|
||||||
|
int main() {
|
||||||
|
/* 初始化无向图 */
|
||||||
|
vector<Vertex*> v = valsToVets(vector<int> { 0, 1, 2, 3, 4, 5, 6 });
|
||||||
|
vector<vector<Vertex*>> edges = { { v[0], v[1] }, { v[0], v[3] }, { v[1], v[2] },
|
||||||
|
{ v[2], v[5] }, { v[4], v[5] }, { v[5], v[6] } };
|
||||||
|
GraphAdjList graph(edges);
|
||||||
|
cout << "\n初始化后,图为" << endl;
|
||||||
|
graph.print();
|
||||||
|
|
||||||
|
/* 深度优先遍历 DFS */
|
||||||
|
vector<Vertex*> res = graphDFS(graph, v[0]);
|
||||||
|
cout << "\n深度优先遍历(DFS)顶点序列为" << endl;
|
||||||
|
PrintUtil::printVector(vetsToVals(res));
|
||||||
|
|
||||||
|
// 释放内存
|
||||||
|
for (Vertex *vet : v) {
|
||||||
|
delete vet;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -8,17 +8,17 @@
|
|||||||
|
|
||||||
|
|
||||||
/* 双向链表结点 */
|
/* 双向链表结点 */
|
||||||
struct DoubleListNode {
|
struct DoublyListNode {
|
||||||
int val; // 结点值
|
int val; // 结点值
|
||||||
DoubleListNode *next; // 后继结点指针
|
DoublyListNode *next; // 后继结点指针
|
||||||
DoubleListNode *prev; // 前驱结点指针
|
DoublyListNode *prev; // 前驱结点指针
|
||||||
DoubleListNode(int val) : val(val), prev(nullptr), next(nullptr) {}
|
DoublyListNode(int val) : val(val), prev(nullptr), next(nullptr) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
/* 基于双向链表实现的双向队列 */
|
/* 基于双向链表实现的双向队列 */
|
||||||
class LinkedListDeque {
|
class LinkedListDeque {
|
||||||
private:
|
private:
|
||||||
DoubleListNode *front, *rear; // 头结点 front ,尾结点 rear
|
DoublyListNode *front, *rear; // 头结点 front ,尾结点 rear
|
||||||
int queSize = 0; // 双向队列的长度
|
int queSize = 0; // 双向队列的长度
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -28,7 +28,7 @@ public:
|
|||||||
/* 析构方法 */
|
/* 析构方法 */
|
||||||
~LinkedListDeque() {
|
~LinkedListDeque() {
|
||||||
// 释放内存
|
// 释放内存
|
||||||
DoubleListNode *pre, *cur = front;
|
DoublyListNode *pre, *cur = front;
|
||||||
while (cur != nullptr) {
|
while (cur != nullptr) {
|
||||||
pre = cur;
|
pre = cur;
|
||||||
cur = cur->next;
|
cur = cur->next;
|
||||||
@ -48,7 +48,7 @@ public:
|
|||||||
|
|
||||||
/* 入队操作 */
|
/* 入队操作 */
|
||||||
void push(int num, bool isFront) {
|
void push(int num, bool isFront) {
|
||||||
DoubleListNode *node = new DoubleListNode(num);
|
DoublyListNode *node = new DoublyListNode(num);
|
||||||
// 若链表为空,则令 front, rear 都指向 node
|
// 若链表为空,则令 front, rear 都指向 node
|
||||||
if (isEmpty())
|
if (isEmpty())
|
||||||
front = rear = node;
|
front = rear = node;
|
||||||
@ -88,7 +88,7 @@ public:
|
|||||||
if (isFront) {
|
if (isFront) {
|
||||||
val = front->val; // 暂存头结点值
|
val = front->val; // 暂存头结点值
|
||||||
// 删除头结点
|
// 删除头结点
|
||||||
DoubleListNode *fNext = front->next;
|
DoublyListNode *fNext = front->next;
|
||||||
if (fNext != nullptr) {
|
if (fNext != nullptr) {
|
||||||
fNext->prev = nullptr;
|
fNext->prev = nullptr;
|
||||||
front->next = nullptr;
|
front->next = nullptr;
|
||||||
@ -98,7 +98,7 @@ public:
|
|||||||
} else {
|
} else {
|
||||||
val = rear->val; // 暂存尾结点值
|
val = rear->val; // 暂存尾结点值
|
||||||
// 删除尾结点
|
// 删除尾结点
|
||||||
DoubleListNode *rPrev = rear->prev;
|
DoublyListNode *rPrev = rear->prev;
|
||||||
if (rPrev != nullptr) {
|
if (rPrev != nullptr) {
|
||||||
rPrev->next = nullptr;
|
rPrev->next = nullptr;
|
||||||
rear->prev = nullptr;
|
rear->prev = nullptr;
|
||||||
@ -131,7 +131,7 @@ public:
|
|||||||
|
|
||||||
/* 返回数组用于打印 */
|
/* 返回数组用于打印 */
|
||||||
vector<int> toVector() {
|
vector<int> toVector() {
|
||||||
DoubleListNode *node = front;
|
DoublyListNode *node = front;
|
||||||
vector<int> res(size());
|
vector<int> res(size());
|
||||||
for (int i = 0; i < res.size(); i++) {
|
for (int i = 0; i < res.size(); i++) {
|
||||||
res[i] = node->val;
|
res[i] = node->val;
|
||||||
|
34
codes/cpp/include/Vertex.hpp
Normal file
34
codes/cpp/include/Vertex.hpp
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
/**
|
||||||
|
* File: PrintUtil.hpp
|
||||||
|
* Created Time: 2023-03-02
|
||||||
|
* Author: Krahets (krahets@163.com)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
/* 顶点类 */
|
||||||
|
struct Vertex {
|
||||||
|
int val;
|
||||||
|
Vertex(int x) : val(x) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 输入值列表 vals ,返回顶点列表 vets */
|
||||||
|
vector<Vertex*> valsToVets(vector<int> vals) {
|
||||||
|
vector<Vertex*> vets;
|
||||||
|
for (int val : vals) {
|
||||||
|
vets.push_back(new Vertex(val));
|
||||||
|
}
|
||||||
|
return vets;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 输入顶点列表 vets ,返回值列表 vals */
|
||||||
|
vector<int> vetsToVals(vector<Vertex*> vets) {
|
||||||
|
vector<int> vals;
|
||||||
|
for (Vertex *vet : vets) {
|
||||||
|
vals.push_back(vet->val);
|
||||||
|
}
|
||||||
|
return vals;
|
||||||
|
}
|
@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
#include "ListNode.hpp"
|
#include "ListNode.hpp"
|
||||||
#include "TreeNode.hpp"
|
#include "TreeNode.hpp"
|
||||||
|
#include "Vertex.hpp"
|
||||||
#include "PrintUtil.hpp"
|
#include "PrintUtil.hpp"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
@ -84,7 +84,8 @@ public class graph_adjacency_list {
|
|||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
/* 初始化无向图 */
|
/* 初始化无向图 */
|
||||||
Vertex[] v = Vertex.valsToVets(new int[] { 1, 3, 2, 5, 4 });
|
Vertex[] v = Vertex.valsToVets(new int[] { 1, 3, 2, 5, 4 });
|
||||||
Vertex[][] edges = { { v[0], v[1] }, { v[0], v[3] }, { v[1], v[2] }, { v[2], v[3] }, { v[2], v[4] }, { v[3], v[4] } };
|
Vertex[][] edges = { { v[0], v[1] }, { v[0], v[3] }, { v[1], v[2] },
|
||||||
|
{ v[2], v[3] }, { v[2], v[4] }, { v[3], v[4] } };
|
||||||
GraphAdjList graph = new GraphAdjList(edges);
|
GraphAdjList graph = new GraphAdjList(edges);
|
||||||
System.out.println("\n初始化后,图为");
|
System.out.println("\n初始化后,图为");
|
||||||
graph.print();
|
graph.print();
|
||||||
|
@ -325,7 +325,7 @@
|
|||||||
=== "C++"
|
=== "C++"
|
||||||
|
|
||||||
```cpp title="linkedlist_deque.cpp"
|
```cpp title="linkedlist_deque.cpp"
|
||||||
[class]{ListNode}-[func]{}
|
[class]{DoublyListNode}-[func]{}
|
||||||
|
|
||||||
[class]{LinkedListDeque}-[func]{}
|
[class]{LinkedListDeque}-[func]{}
|
||||||
```
|
```
|
||||||
|
@ -64,8 +64,6 @@ hide:
|
|||||||
|
|
||||||
如果你也有上述烦恼,那么很幸运这本书找到了你。本书是我对于该问题给出的答案,虽然不一定正确,但至少代表一次积极的尝试。这本书虽然不足以让你直接拿到 Offer ,但会引导你探索数据结构与算法的“知识地图”,带你了解不同“地雷”的形状大小和分布位置,让你掌握各种“排雷方法”。有了这些本领,相信你可以更加得心应手地刷题与阅读文献,逐步搭建起完整的知识体系。
|
如果你也有上述烦恼,那么很幸运这本书找到了你。本书是我对于该问题给出的答案,虽然不一定正确,但至少代表一次积极的尝试。这本书虽然不足以让你直接拿到 Offer ,但会引导你探索数据结构与算法的“知识地图”,带你了解不同“地雷”的形状大小和分布位置,让你掌握各种“排雷方法”。有了这些本领,相信你可以更加得心应手地刷题与阅读文献,逐步搭建起完整的知识体系。
|
||||||
|
|
||||||
书中的代码均配有可一键运行的源文件,托管在 [github.com/krahets/hello-algo](https://github.com/krahets/hello-algo) 仓库,建议前往下载。发行版 PDF 的更新周期较长,想看最新内容的小伙伴可以前往 [www.hello-algo.com](https://www.hello-algo.com/) 网页版。
|
|
||||||
|
|
||||||
<h3 align="left"> 作者简介 </h3>
|
<h3 align="left"> 作者简介 </h3>
|
||||||
|
|
||||||
靳宇栋 (Krahets),大厂高级算法工程师,上海交通大学硕士。力扣(LeetCode)全网阅读量最高博主,其 LeetBook《图解算法数据结构》已被订阅 22 万本。
|
靳宇栋 (Krahets),大厂高级算法工程师,上海交通大学硕士。力扣(LeetCode)全网阅读量最高博主,其 LeetBook《图解算法数据结构》已被订阅 22 万本。
|
||||||
|
Loading…
Reference in New Issue
Block a user