使用C++编写一个图的深度和广度优先遍历的代码

简介: 使用C++编写一个图的深度和广度优先遍历的代码

下面是图的深度优先遍历的代码

//qq460219753获取更多代码
#include <iostream>
#include <vector>
#include <stack>
using namespace std;
// 定义一个图节点结构体
struct GraphNode {
    int val;
    vector<GraphNode*> neighbors;
    GraphNode(int x) : val(x) {};
};
// 深度优先遍历函数
void DFS(GraphNode* node, vector<bool>& visited) {
    // 如果节点已经被访问过,则直接返回
    if (visited[node->val]) {
        return;
    }
    // 输出当前节点的值,并将其标记为已访问
    cout << node->val << " ";
    visited[node->val] = true;
    // 遍历当前节点的所有邻居节点
    for (int i = 0; i < node->neighbors.size(); i++) {
        // 对于每个未访问过的邻居节点,递归调用DFS函数
        if (!visited[node->neighbors[i]->val]) {
            DFS(node->neighbors[i], visited);
        }
    }
}
int main() {
    // 构建一个有向图
    GraphNode* node0 = new GraphNode(0);
    GraphNode* node1 = new GraphNode(1);
    GraphNode* node2 = new GraphNode(2);
    GraphNode* node3 = new GraphNode(3);
    GraphNode* node4 = new GraphNode(4);
    node0->neighbors.push_back(node1);
    node0->neighbors.push_back(node2);
    node1->neighbors.push_back(node2);
    node2->neighbors.push_back(node0);
    node2->neighbors.push_back(node3);
    node3->neighbors.push_back(node3);
    node4->neighbors.push_back(node2);
    node4->neighbors.push_back(node3);
    // 初始化visited数组,所有节点均未被访问过
    vector<bool> visited(5, false);
    // 从节点0开始进行深度优先遍历
    DFS(node0, visited);
    return 0;
}

注释:

定义一个图节点结构体,包含节点的值和邻居节点数组。

定义深度优先遍历函数,输入参数为当前节点和一个表示每个节点是否被访问过的visited数组。

如果当前节点已经被访问过,则直接返回。

输出当前节点的值,并将其标记为已访问。

遍历当前节点的所有邻居节点。

对于每个未访问过的邻居节点,递归调用DFS函数。

在main函数中,构建一个有向图,并初始化visited数组。

从节点0开始进行深度优先遍历。

返回0,表示程序正常结束。

下面是图的广度优先遍历的代码

#include <iostream>
#include <vector>
#include <queue>
#include <unordered_set>
using namespace std;
// 定义图节点结构体
struct GraphNode {
    int val;  // 节点的值
    vector<GraphNode*> neighbors;  // 节点的邻居
    GraphNode(int x) : val(x) {}
};
// 广度优先遍历函数
void bfs(GraphNode* node) {
    // 定义一个队列来存储遍历到的节点
    queue<GraphNode*> q;
    // 定义一个哈希表来存储已经遍历过的节点
    unordered_set<GraphNode*> visited;
    // 将起始节点加入队列
    q.push(node);
    // 将起始节点标记为已访问
    visited.insert(node);
    // 当队列不为空时,继续遍历
    while (!q.empty()) {
        // 取出队列中的节点
        GraphNode* curr = q.front();
        q.pop();
        // 对当前节点进行操作,这里只是打印节点的值
        cout << curr->val << " ";
        // 遍历当前节点的所有邻居
        for (auto neighbor : curr->neighbors) {
            // 如果邻居节点未被访问过,将其加入队列和已访问哈希表
            if (visited.find(neighbor) == visited.end()) {
                q.push(neighbor);
                visited.insert(neighbor);
            }
        }
    }
}
// 主函数
int main() {
    // 构建一个图
    GraphNode* node0 = new GraphNode(0);
    GraphNode* node1 = new GraphNode(1);
    GraphNode* node2 = new GraphNode(2);
    GraphNode* node3 = new GraphNode(3);
    node0->neighbors = {node1, node2};
    node1->neighbors = {node2, node3};
    node2->neighbors = {node0, node3};
    node3->neighbors = {node3};
    // 对图进行广度优先遍历
    bfs(node0);
    return 0;
}

代码解释:

定义了一个 GraphNode 结构体,用来表示图的节点。其中包含一个整型变量 val 表示节点的值,以及一个 vector 类型的变量 neighbors 表示节点的邻居。

定义了 bfs 函数,用来进行广度优先遍历。函数的参数是起始节点 node。在函数中,首先定义了一个队列 q 来存储遍历到的节点,以及一个哈希表 visited 来存储已经遍历过的节点。将起始节点加入队列,并将其标记为已访问。当队列不为空时,取出队列中的节点,对其进行操作(这里只是打印节点的值),然后遍历当前节点的所有邻居。如果邻居节点未被访问过,将其加入队列和已访问哈希表,直到队列为空。

在主函数中,构建了一个图,并对其进行广度优先遍历。具体地,构建了四个节点,分别为 node0、node1、node2 和 node3,然后将它们的邻居连接起来,形成了一个简单的无向图。最后,将起始节点 node0 传入 bfs 函数中进行遍历。

在函数中,使用了 queue 来存储遍历到的节点。queue 是标准库中的一个容器,用来实现队列数据结构。其成员函数包括 push(向队列尾部添加元素)、front(获取队列头部元素)和 pop(删除队列头部元素)等。

同时,使用了 unordered_set 来存储已经遍历过的节点。unordered_set 是标准库中的一个容器,用来实现哈希表数据结构。其成员函数包括 insert(向哈希表中添加元素)、find(查找指定元素是否在哈希表中)等。

在函数中,使用了 auto 关键字来自动推断变量类型。这个关键字在 C++11 中引入,可以根据变量的初始化表达式自动推断其类型,从而简化代码。


相关文章
|
3月前
|
C++
C++ 语言异常处理实战:在编程潮流中坚守稳定,开启代码可靠之旅
【8月更文挑战第22天】C++的异常处理机制是确保程序稳定的关键特性。它允许程序在遇到错误时优雅地响应而非直接崩溃。通过`throw`抛出异常,并用`catch`捕获处理,可使程序控制流跳转至错误处理代码。例如,在进行除法运算或文件读取时,若发生除数为零或文件无法打开等错误,则可通过抛出异常并在调用处捕获来妥善处理这些情况。恰当使用异常处理能显著提升程序的健壮性和维护性。
76 2
|
3月前
|
算法框架/工具 C++ Python
根据相机旋转矩阵求解三个轴的旋转角/欧拉角/姿态角 或 旋转矩阵与欧拉角(Euler Angles)之间的相互转换,以及python和C++代码实现
根据相机旋转矩阵求解三个轴的旋转角/欧拉角/姿态角 或 旋转矩阵与欧拉角(Euler Angles)之间的相互转换,以及python和C++代码实现
241 0
|
11天前
|
算法 安全 C++
提高C/C++代码的可读性
提高C/C++代码的可读性
30 4
|
1月前
|
Linux C语言 C++
vsCode远程执行c和c++代码并操控linux服务器完整教程
这篇文章提供了一个完整的教程,介绍如何在Visual Studio Code中配置和使用插件来远程执行C和C++代码,并操控Linux服务器,包括安装VSCode、安装插件、配置插件、配置编译工具、升级glibc和编写代码进行调试的步骤。
248 0
vsCode远程执行c和c++代码并操控linux服务器完整教程
|
2月前
|
C++
继续更新完善:C++ 结构体代码转MASM32代码
继续更新完善:C++ 结构体代码转MASM32代码
|
2月前
|
C++ Windows
HTML+JavaScript构建C++类代码一键转换MASM32代码平台
HTML+JavaScript构建C++类代码一键转换MASM32代码平台
|
2月前
|
C++
2合1,整合C++类(Class)代码转换为MASM32代码的平台
2合1,整合C++类(Class)代码转换为MASM32代码的平台
|
2月前
|
前端开发 C++ Windows
C++生成QML代码与QML里面集成QWidget
这篇文章介绍了如何在C++中生成QML代码,以及如何在QML中集成QWidget,包括使用Qt Widgets嵌入到QML界面中的技术示例。
|
3月前
|
程序员 C++ 开发者
C++命名空间揭秘:一招解决全局冲突,让你的代码模块化战斗值飙升!
【8月更文挑战第22天】在C++中,命名空间是解决命名冲突的关键机制,它帮助开发者组织代码并提升可维护性。本文通过一个图形库开发案例,展示了如何利用命名空间避免圆形和矩形类间的命名冲突。通过定义和实现这些类,并在主函数中使用命名空间创建对象及调用方法,我们不仅解决了冲突问题,还提高了代码的模块化程度和组织结构。这为实际项目开发提供了宝贵的参考经验。
63 2
|
3月前
|
C++
拥抱C++面向对象编程,解锁软件开发新境界!从混乱到有序,你的代码也能成为高效能战士!
【8月更文挑战第22天】C++凭借其强大的面向对象编程(OOP)能力,在构建复杂软件系统时不可或缺。OOP通过封装数据和操作这些数据的方法于对象中,提升了代码的模块化、重用性和可扩展性。非OOP方式(过程化编程)下,数据与处理逻辑分离,导致维护困难。而OOP将学生信息及其操作整合到`Student`类中,增强代码的可读性和可维护性。通过示例对比,可以看出OOP使C++代码结构更清晰,特别是在大型项目中,能有效提高开发效率和软件质量。
34 1