hnust 1966: 广度优先搜索

hnust 1966: 广度优先搜索

题目描述

输入一个图,用邻接表存储(实际上也可以选择邻接矩阵),并实现BFS操作。

拷贝前面已经实现的代码,主函数必须如下,完成剩下的部分。

int main()

{

Graph g;

CreateUDG(g);

BFS(g, 0);//从0号顶点开始遍历

DestroyUDG(g);

return 0;

}//main

输入

输入的第一行是两个整数,分别是图的总顶点数n和总边数e

第二行是n个空格分开的字符串,是顶点的名字,依次对应编号0~n-1。

随后有e行,每行两个空格分开的顶点名字,表示一条边的两个顶点。

具体见样例。

输出

输出图的BFS序列,遍历次序按教材,每个顶点后面跟一个空格。

具体见样例。

样例输入 Copy

8 9

v1 v2 v3 v4 v5 v6 v7 v8

v1 v2

v1 v3

v2 v4

v2 v5

v3 v6

v3 v7

v4 v8

v5 v8

v6 v7

样例输出 Copy

v1 v2 v3 v4 v5 v6 v7 v8

提示

样例对应教材6.5的图G4

解题过程

注:本题按照书上算法解析完成,广度优先搜索的细化代码及函数分解请看合集《2024.6 hnust 23级 数据结构 课程设计》"推箱子游戏-广度优先搜索版本"

图的广度优先搜索(BFS)需要借助到队列来遍历:

①首先,选取图中某一顶点vi作为出发点,访问后将其入队并标记为已访问(使用队列用于避免重复访问,存放已经访问过的各邻接顶点);

②依次访问与vi邻接的顶点,即当队列不为空时检查出队顶点的所有邻接顶点,访问未被访问的邻接顶点并将其入队,重复该过程;【可概括为由起始顶点开始,按照广度优先的顺序逐层遍历与当前顶点相邻的顶点将其访问】

③当队列为空时跳出循环,即所有已被访问的顶点的邻接顶点均被访问到,则此时遍历完成。

(二)BFS的空间复杂度和时间复杂度

对于一个图G=(V,E),由顶点集V和边集E组成。

1、BFS算法的空间复杂度

通过BFS遍历的空间复杂度为O(|V|)。

2、BFS算法的时间复杂度

时间复杂度取决于图的存储结构,若通过邻接矩阵表示图,则查找顶点的邻接顶点所需时间为O(|V|),总时间复杂度为O(|V2|)(邻接矩阵为方阵n×n),这和DFS算法的时间复杂度是一样的;若通过邻接表表示图,则每个顶点都入队一次,即所需时间为O(|V|),搜索顶点的邻接顶点所需时间为O(|E|),其时间复杂度为O(|V|+|E|)。

这段C++代码实现了一个基于广度优先搜索(BFS)的无向图的拓扑排序算法。以下是对代码的详细解析:

  1. 头文件和命名空间:

    • 包含 <bits/stdc++.h> 头文件,它包含了标准库中的大部分内容。
    • 使用 using namespace std; 来避免在标准库类型和函数前加 std::。
  2. 读取图的参数:

    • 读取两个整数 n 和 e,分别代表图中顶点的数量和边的数量。
  3. 存储顶点信息:

    • 创建一个字符串数组 nodes 来存储顶点的名称。
  4. 输入顶点名称:

    • 使用循环读取 n 个顶点的名称。
  5. 建立顶点位置映射:

    • 使用 map(映射)来存储每个顶点名称与其在数组中的索引位置。
  6. 创建无向图:

    • 使用 map 来创建一个邻接表 G,表示无向图中的边。
  7. 对邻接表进行排序:

    • 对每个顶点的邻接表进行排序,以便在后续的搜索中按顺序访问。
  8. 初始化访问标记:

    • 使用 map 初始化所有顶点的访问状态为未访问。
  9. 使用队列实现BFS:

    • 使用 queue 来实现BFS,首先将起始顶点压入队列,并标记为已访问。
  10. BFS搜索:

    • 当队列不为空时,执行循环:
      • 弹出队列前端元素作为当前访问的顶点,并输出。
      • 遍历当前顶点的所有邻接顶点。
      • 如果邻接顶点未被访问,将其标记为已访问,并压入队列。
  11. 输出访问顺序:

    • 在访问过程中,每访问一个顶点,就输出其名称。
  12. 程序结束:

    • 当队列为空时,表示所有顶点都被访问完毕,程序结束。

代码逻辑分析:

  • 这段代码通过BFS实现了拓扑排序,适用于无向图。
  • 使用队列来存储待访问的顶点,使用映射来记录顶点的访问状态和位置信息。

潜在问题:

  • 代码中注释掉的部分提供了另一种实现拓扑排序的方法,但在当前实现中未使用。

改进建议:

  • 考虑使用 std::vector 替代数组,以提高代码的安全性和灵活性。
  • 考虑使用 std::unordered_map 替代 std::map,以提高查找效率。
  • 如果需要处理更大的图或更复杂的图结构,可以考虑优化内存使用和搜索算法。
  • 代码中的排序部分可能不是必要的,因为拓扑排序的目的是线性化图,而不是排序顶点。如果不需要对顶点进行排序,可以省略排序逻辑。

AC代码

c 复制代码
#include<bits/stdc++.h>
using namespace std;
  
int main(int argc, char const *argv[])
{
    map < string , std::vector<string> >  G;
    int n ,e;
    cin>> n >> e;  //输入:8 9
  
    string nodes[n];
    for (int i = 0; i < n; ++i)
    {
        cin >> nodes[i];  //输入:v1 v2 v3 v4 v5 v6 v7 v8
    }
  
    map <string , int > location;
    for (int i = 0; i < n; ++i)   //排序数组
    {
        location[nodes[i]] = i;
    }
  
    for (int i = 0; i < e; ++i)  //创建无向图
    {
        string l,r;
        cin >> l >> r;
        G[l].push_back(r);
        G[r].push_back(l);
    }
  
    for (int i = 0; i < n; ++i)  //对无向图的排序
    {
        int j = G[nodes[i]].size();
        for (int p = 0; p < j; ++p)
        {
            for (int q = 0; q < j; ++q)
            {
                if(location[G[nodes[i]][q]] > location[G[nodes[i]][p]])
                {
                    string temp;
                    temp = G[nodes[i]][q];
                    G[nodes[i]][q] = G[nodes[i]][p];
                    G[nodes[i]][p] = temp;
                }
            }
        }
    }
  
    map < string , bool > vis;  //是否被访问
    queue < string > q;
    q.push(nodes[0]);
    vis[nodes[0]] = true;
    // string rev[n];
    // int r = 0;
  
    while(q.size())
    {
        string curr;
        curr = q.front();  q.pop();
        // rev[r++] = curr;
        cout << curr << " ";
  
        for(auto next : G[curr])
        {
            if(!vis[next])
            {
                vis[next] = true;
                q.push(next);
            }
        }
    }
    return 0;
}
 
相关推荐
Frank_refuel3 小时前
C++11之一场名为“搬家”的 C++ 之旅
开发语言·c++
hetao17338375 小时前
2026-10-03~04 hetao1733837 的刷题记录
c++·算法
Zootopia6266 小时前
飞行力学知识梳理1|飞行性能与稳定性
人工智能·python·算法·机器学习·无人机·学习方法·信息与通信
longlongzihan6 小时前
从LeetCode 70. 爬楼梯看动态规划:如何精准推导状态转移方程?
c++·算法·leetcode·动态规划
2601_960356387 小时前
2027校招采购岗解析:数学基础如何迁移到需求预测、成本与供应商分析
人工智能·算法
h_a_o777oah7 小时前
【树论】树链剖分:将树形结构转化为线性结构以处理树上路径问题(洛谷 P3384 附C++代码模板)
数据结构·算法·线段树·acm·树链剖分·树论·重链剖分
HEJOO97 小时前
指针的算术运算详解
java·数据结构·算法
Coder-magician7 小时前
《代码随想录》刷题打卡day47:并查集-part01
数据结构·算法·图论
垆边人似月.7 小时前
VLAN 资源池(100~200 分档)
数据结构·算法
潼心1412o8 小时前
C++初阶(长期更新)第6讲:类和对象(下)
开发语言·c++·算法