c# 广度优先搜索(Breadth-First Search,BFS)

        在这篇文章中我将讨论用于树和图的两种遍历机制之一。将使用 C# 示例介绍广度优先搜索 (BFS)。图是最具挑战性和最复杂的数据结构之一。

        广度优先搜索的工作原理:广度优先搜索 (BFS)是一种探索树或图的方法。在 BFS 中,您首先探索一步之外的所有节点,然后探索两步之外的所有节点,依此类推。

        如果我们熟悉广度优先搜索,那么理解系统设计概念和破解面试问题就会很容易。

        广度优先搜索就像向池塘中心扔一块石头。您探索的节点从起点“产生涟漪”。

以下是 BFS 从根开始遍历这棵树的方式:

广度优先优先遍历树
        在上图的第一张图中,我们从最顶层的节点开始。

        在第二张图中,我们遍历第二层存在的所有节点。在第三张图像中,所有节点都出现在第三层,依此类推。直到我们到达终点。

优点:

BFS 将找到  起点和任何其他可到达节点之间的最短路径。深度优先搜索不一定能找到最短路径。
缺点:

二叉树上的 BFS 通常 比 DFS 需要更多的内存。

示例一:

广度优先搜索代码示例
在下面的代码中,我尝试创建与下图所示相同的结构。

static void Main(string[] args)
        {
             IDictionary> tree = new Dictionary>();
            tree[1] = new List { 2, 3, 4 };
            tree[2] = new List { 5 };
            tree[3] = new List { 6, 7 };
            tree[4] = new List { 8 };
            tree[5] = new List { 9 };
            tree[6] = new List { 10 };
            HashSet itemCovered = new HashSet();
            Queue queue = new Queue();
            queue.Enqueue(tree.ElementAt(0).Key);
            while (queue.Count > 0)
            {
                var element = queue.Dequeue();
                if (itemCovered.Contains(Convert.ToInt32(element)))
                    continue;
                else
                    itemCovered.Add(Convert.ToInt32(element));
                Console.WriteLine(element);
                List neighbours;
                tree.TryGetValue(Convert.ToInt32(element), out neighbours);
                if (neighbours == null)
                    continue;
                foreach (var item1 in neighbours)
                {
                    queue.Enqueue(item1);
                }
            }
        }
}

我正在上面的代码中执行以下步骤来遍历树:

首先水平移动,访问当前层的所有节点
移动到下一层
我正在使用队列来推送正在遍历的项目,并将该项目的所有邻居添加到队列中。一旦遍历将它们弹出。

上述代码的输出如下图所示:

广度优先搜索问题:
给定 root 二叉树的 ,返回  树 中每一行中最大值的数组(从 0 开始索引)。 

解决方案:
作为解决方案的一部分,我们将遍历一级的所有节点并尝试找到最大节点。
1、将根节点添加到队列中。
2、遍历队列,直到队列为空。
3、获取队列中元素的数量。
4、遍历元素直到计数为止。
5、获取内循环中的最大值。

public int[] FindLargestValueinEachTreeRowMethod(TreeNode root)
        {
            List<int> result = new List<int>();
            if (root == null) return result.ToArray();

            Queue dfs_queue = new Queue();
            dfs_queue.Enqueue(root);

            while (dfs_queue.Count > 0)
            {
                int max_value = Int32.MinValue;
                int elements_count = dfs_queue.Count;

                for (int i = 0; i <= elements_count; i++)
                {
                    TreeNode node = dfs_queue.Dequeue();
                    max_value = Math.Max((int)max_value, (int)node.val);
                    if (node.left != null) dfs_queue.Enqueue(node.left);
                    if (node.right != null) dfs_queue.Enqueue(node.right);
                }

                result.Add(max_value);
            }

            return result.ToArray();
            
        }

广度优先搜索的实际应用:
我被问到一个与 BFS 相关的非常有用且有趣的编程面试问题。下面是问题。

给你一张地铁站的网格图,编写一个函数来输出从每个路口到最近车站的距离。从一个点到另一个点时,你不能沿对角线移动。答案有点复杂,但也不是很难。

输入:

。。。。。X
。。。。。。
。。。。。。
。X 。。。。
。。。。X 。

输出:

4 3 3 2 1 0 3
2 3 3
2 1 2 1 2 3 2
2 1 0 1 2 1 2
2 1 2 1 0 1

示例二:

图是数据结构和算法中非常重要的话题

class BfsGraph
   {
       LinkedList<int>[] _adj;
       int _V;

       public BfsGraph(int v)
       {
           _adj = new LinkedList<int>[v];

           for (int i = 0; i < v; i++)
           {
               _adj[i] = new LinkedList<int>();
           }
           _V = v;

       }

       public void AddEdge(int v, int w)
       {
           _adj[v].AddLast(w);
       }

       public void BFS(int v)
       {

           Queue<int> q = new Queue<int>();
           bool[] flag = new bool[_V];


           q.Enqueue(v);
           flag[v] = true;
           Console.WriteLine(v);

           while (q.Count > 0)
           {
               int w = q.Dequeue();
               LinkedList<int> linledList = _adj[w];
               LinkedListNode<int> currentNode = linledList.First;
               while (currentNode != null && !flag[currentNode.Value])
               {
                   Console.WriteLine(currentNode.Value);
                   q.Enqueue(currentNode.Value);
                   flag[currentNode.Value] = true;
                   currentNode = currentNode.Next;
               }
           }


       }


   }

        上面的 C# 代码定义了一个名为 BfsGraph 的类,它表示图数据结构并实现广度优先搜索 (BFS) 算法。该类有两个实例变量:_adj(表示图的邻接列表的 LinkedList<int> 对象数组)和 _V(表示图中顶点数的 int)。

        BfsGraph 构造函数采用 int 参数 v 表示图中的顶点数。它使用大小为 v 的 LinkedList<int> 对象的新数组初始化 _adj 数组,并将 _V 的值设置为 v。构造函数还使用新的 LinkedList<int> 对象初始化 _adj 数组的每个元素。

        AddEdge 方法采用两个 int 参数 v 和 w,表示图中的两个顶点。它通过将 w 添加到链表末尾 _adj 数组中索引 v 处来在这两个顶点之间添加一条边。

        BFS 方法采用一个 int 参数 v 表示 BFS 遍历的起始顶点。它创建一个新的 Queue<int> 对象来存储要访问的顶点,并创建一个新的 bool[] 数组来跟踪已访问的顶点。该方法将起始顶点 v 排入队列,将标志数组中的相应元素设置为 true,并使用 Console.WriteLine 输出其值。

        然后该方法进入一个循环,一直持续到队列为空为止。在每次迭代中,它都会从队列中出列一个顶点,从 _adj 数组中检索其邻接列表,并使用 while 循环迭代其元素。对于邻接列表中的每个未访问的顶点,它使用 Console.WriteLine 输出其值,将其排队并将其在标志数组中的相应元素设置为 true。

下面的示例演示了如何使用此类创建具有 4 个顶点的图,并从顶点 2 开始执行 BFS 遍历:

var graph = new BfsGraph(4);
graph.AddEdge(0, 1);
graph.AddEdge(0, 2);
graph.AddEdge(1, 2);
graph.AddEdge(2, 0);
graph.AddEdge(2, 3);
graph.AddEdge(3, 3);

Console.WriteLine("Breadth First Traversal starting from vertex 2:");
graph.BFS(2);

此代码创建具有 4 个顶点的 BfsGraph 类的新实例,使用 AddEdge 方法在它们之间添加边,并使用 BFS 方法从顶点 2 开始执行 BFS 遍历。该代码的输出将是:

从顶点开始广度优先遍历 2:
2
0
3

时间复杂度:O(v+e),其中 v 是节点数,e 是边数。

辅助空间:O(v)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/2810075.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

教你 3 分钟用 Hexo 建立一个纯静态、高性能的个人博客

只要会使用命令行&#xff0c;执行简单的命令。那么&#xff0c;用 Hexo 建立一个个人博客的过程&#xff0c;称得上是轻松愉快且简单&#xff01; 我会以 Mac 操作系统作为例子&#xff0c;因为在 Mac 上实现这一切更为简单&#xff0c;因为 Mac 操作系统的命令行环境相对来说…

荣耀MWC发布AI使能的全场景战略

【2024年2月25日&#xff0c;巴塞罗那】荣耀在2024 MWC世界移动通信大会上正式发布了全新的AI使能的全场景战略&#xff0c;推出平台级AI赋能&#xff0c;以人为中心的跨操作系统体验和基于意图识别的全新人机交互&#xff0c;以及与全球合作伙伴合作的荣耀Magic6 Pro&#xff…

前端基础面试题(一)

摘要&#xff1a;最近&#xff0c;看了下慕课2周刷完n道面试题&#xff0c;记录下... 1.请说明Ajax、Fetch、Axios三者的区别 三者都用于网络请求&#xff0c;但维度不同&#xff1a; Ajax&#xff08;Asynchronous Javascript ang XML&#xff09;&#xff0c;是一种在不重新…

Matryoshka Representation Learning (MRL)-俄罗斯套娃向量表征学习

前言 在2024年1月底OpenAI发布新的向量模型&#xff0c;并提到新的向量模型支持将向量维度缩短。向量模型支持缩短维度而又不会威胁到向量的表示能力的原因在于使用了Matryoshka Representation Learning。 Matryoshka Representation Learning (MRL)是2022年发表的论文&#…

Redis 服务集群、哨兵、缓存及持久化的实现原理和应用场景

Redis 是一种高性能的键值存储系统&#xff0c;已经成为了许多企业和互联网公司的核心技术之一。本文将介绍 Redis 的服务集群、哨兵以及缓存实现原理和应用场景&#xff0c;以帮助读者更好地理解和使用 Redis。 引言&#xff1a; 随着互联网应用规模不断扩大&#xff0c;Redi…

RocketMQ - RocketMQ的架构原理和使用方法

1. MQ如何集群化部署来支撑高并发访问 假设RocketMQ部署在一台机器上&#xff0c;即使这台机器的配置很高&#xff0c;但是一般来说一台机器也就支撑10万的并发访问。 这个时候&#xff0c;假设有大量的系统都要往RocketMQ里高并发的额写入消息&#xff0c;可能达到每秒有几十…

canvas水波纹效果,jquery鼠标水波纹插件

canvas水波纹效果&#xff0c;jquery鼠标水波纹插件 效果展示 jQuery水波纹效果&#xff0c;canvas水波纹插件 HTML代码片段 <div class"scroll04wrap"><h3>发展历程</h3><div class"scroll04"><p>不要回头&#xff0c;一…

在苹果电脑MAC上安装Windows10(双系统安装的详细图文步骤教程)

在苹果电脑MAC上安装Windows10&#xff08;双系统安装的详细图文步骤教程&#xff09; 一、准备工作准备项1&#xff1a;U盘作为系统安装盘准备项2&#xff1a;您需要安装的系统镜像 二、启动转换助理步骤1&#xff1a;找到启动转换助理步骤2&#xff1a;启动转换助理步骤3&…

java接受命令行输入

在Java中&#xff0c;你可以使用​​Scanner​​类来接受命令行输入。以下是一个简单的例子&#xff0c;演示如何从命令行接受输入&#xff1a; import java.util.Scanner;public class CommandLineInputExample {public static void main(String[] args) {// 创建一个Scanner…

linux服务器vi文件中文乱码

服务器vi编辑中文乱码 cat 文本是中文 可以编辑 vi /etc/environment 文件修改为utf8中文字符集 LANGzh_CN.UTF-8 LANGUAGEen_US:en LC_CTYPE"zh_CN.UTF-8" LC_NUMERIC"zh_CN.UTF-8" LC_TIME"zh_CN.UTF-8" LC_COLLATE"zh_CN.UTF-8"…

48.仿简道云公式函数实战-文本函数-EXACT

1. EXACT函数 比较两个字符串是否完全相同&#xff08;区分大小写&#xff09;。完全相同则返回 true&#xff0c;否则返回 false。 2. 函数用法 EXACT(text1,text2) 3. 函数示例 比较两个字符串是否完全相同&#xff08;区分大小写&#xff09;。完全相同则返回 true&…

有效涨点,增强型 YOLOV8 与多尺度注意力特征融合,附代码,详细步骤

目录 摘要 结构图 原理 代码实现 添加ymal文件 实验结果 可接论文指导----------> v jiabei-545 完整代码&#xff08;失效 -----------&#x1f446; &#xff09; 执行程序流程 摘要 在本实验中&#xff0c;我们通过将双层路由注意&#xff08;BRA&#xff09;…

python中的 continue break 以及pass

在python中 continue 以及 break 的作用都用于跳出循环,不同的是continue是跳出当前循环,而break是跳出循环 具体图解如下 continue 执行流程图&#xff1a; break 执行流程图&#xff1a; 他们两个在while循环和for循环中分别为 在for循环中执行过程为 当循环体执行到cont…

linux---nginx基础

目录 一、Nginx的概念 二、Nginx常用功能 1、HTTP(正向)代理&#xff0c;反向代理 1.1正向代理 1.2 反向代理 2、负载均衡 2.1 轮询法&#xff08;默认方法&#xff09; 2.2 weight权重模式&#xff08;加权轮询&#xff09; 2.3 ip_hash 3、web缓存 三、基础特性 四…

Jitsi Meet 大型视频会议调优方案

jitsi meet 大型视频会议调优方案 在举办一些大型会议的时候,比如100个人会议,为了节约宽带和节省资源,我们并不会选择传输全部的音视频资源。 举个例子,比如100个人线下会议,如果大家都说话的情况下,大家要么听不清,要么听得是声音最大的那几个人。 视频会议也可以借…

赵丽颖林更新《与凤行》传乌龙!惊艳特效惹争议

古装偶像剧《与凤行》是收视女王赵丽颖和实力小生林更新继《楚乔传》的再度合作&#xff0c;“星月”CP时隔多年的二搭还没开播&#xff0c;就已经把观众的期待值高高拉起。 《与凤行》预告惊艳四座&#xff0c;特效究竟出自谁手&#xff1f; 观众早已苦“五毛特效”久矣&…

项目:shell实现多级菜单脚本编写

目录 1. 提示 2. 演示效果 2.1. 一级菜单 2.2. 二级菜单 2.3. 执行操作 3. 参考代码 1. 提示 本脚本主要实现多级菜单效果&#xff0c;并没有安装LAMP、LNMP环境&#xff0c;如果要用在实际生成环境中部署LNMP、LAMP环境&#xff0c;只需要简单修改一下就可以了。 2. 演…

Pycharm环境中,python为变量赋值的时候,如何自动添加空格?

在python中&#xff0c;为变量赋值的时候&#xff0c;如果没有加入空格&#xff0c;代码底部会有灰色波浪线&#xff0c;说明不符合Python规范。 可以在菜单栏选择code&#xff0c;reformat code。重新格式化代码&#xff0c;所有代码会自动格式化。 快捷方式为&#xff1a;ct…

java数据结构与算法刷题-----LeetCode98. 验证二叉搜索树

java数据结构与算法刷题目录&#xff08;剑指Offer、LeetCode、ACM&#xff09;-----主目录-----持续更新(进不去说明我没写完)&#xff1a;https://blog.csdn.net/grd_java/article/details/123063846 文章目录 1. 法一&#xff1a;利用BST性质进行递归2. 法二&#xff1a;利用…

CUDA 编程指南 —— 编程接口之CUDA Runtime

目录 CUDA Runtime 运行时在 cudart 库中实现&#xff0c;该库通过 cudart.lib 或 libcudart.a 静态链接到应用程序&#xff0c;或者通过 cudart.dll 或 libcudart.so 动态链接到应用程序。需要 cudart.dll 和/或 cudart.so 进行动态链接的应用程序通常将它们作为应用程序安装…