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. 读取图的参数

    • 读取两个整数 ne,分别代表图中顶点的数量和边的数量。
  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;
}
 
相关推荐
小于不是小鱼呀3 分钟前
手撕 K-Means
人工智能·算法·机器学习
m0_740154675 分钟前
K-Means颜色变卦和渐变色
算法·机器学习·kmeans
liulun23 分钟前
Skia如何绘制几何图形
c++·windows
old_power29 分钟前
UCRT 和 MSVC 的区别(Windows 平台上 C/C++ 开发相关)
c语言·c++·windows
东皇太星37 分钟前
SIFT算法详细原理与应用
图像处理·算法·计算机视觉
獨枭44 分钟前
彻底解决 MFC 自绘控件闪烁
c++·mfc
獨枭1 小时前
MFC Resource.h 文件详解与修改指南
c++·mfc
鑫鑫向栄1 小时前
[蓝桥杯]堆的计数
数据结构·c++·算法·蓝桥杯·动态规划
緈福的街口1 小时前
【leetcode】3. 无重复字符的最长子串
算法·leetcode·职场和发展
@老蝴1 小时前
C语言 — 编译和链接
c语言·开发语言