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://www.hqwc.cn/news/491975.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C# Onnx Yolov8-OBB 旋转目标检测

目录 效果 模型信息 项目 代码 下载 C# Onnx Yolov8-OBB 旋转目标检测 效果 模型信息 Model Properties ------------------------- date&#xff1a;2024-02-26T08:38:44.171849 description&#xff1a;Ultralytics YOLOv8s-obb model trained on runs/DOTAv1.0-ms.ya…

LabVIEW燃料电池船舶电力推进监控系统

LabVIEW燃料电池船舶电力推进监控系统 随着全球经济一体化的推进&#xff0c;航运业的发展显得尤为重要&#xff0c;大约80%的世界贸易依靠海上运输实现。传统的船舶推进系统主要依赖于柴油机&#xff0c;这不仅耗能高&#xff0c;而且排放严重&#xff0c;对资源和环境的影响…

WPF 开发调试比较:Visual Studio 原生和Snoop调试控制台

文章目录 前言运行环境简单的WPF代码实现一个简单的ListBoxVisual Studio自带代码调试热重置功能测试实时可视化树查找窗口元素显示属性 Snoop调试使用Snoop简单使用调试控制台元素追踪结构树Visual/可视化结构树Logical/本地代码可视化树AutoMation/自动识别结构树 WPF元素控制…

100天精通Python(实用脚本篇)——第117天:基于selenium实现反反爬策略之代码输入账号信息登录网站

文章目录 专栏导读1. 前言2. 实现步骤3. 基础补充4. 代码实战4.1 创建连接4.2 添加请求头伪装浏览器4.3 隐藏浏览器指纹4.4 最大化窗口4.5 启动网页4.6 点击密码登录4.7 输入账号密码4.8 点击登录按钮4.9 完整代码4.10 GIF动图展示 五、总结 专栏导读 &#x1f525;&#x1f5…

【Android12】Monkey压力测试源码执行流程分析

Monkey压力测试源码执行流程分析 Monkey是Android提供的用于应用程序自动化测试、压力测试的测试工具。 其源码路径(Android12)位于 /development/cmds/monkey/部署形式为Java Binary # development/cmds/monkey/Android.bp // Copyright 2008 The Android Open Source Proj…

发电机测试的常见参数和规格有哪些需要关注?

发电机测试是确保其正常运行和性能的关键步骤。在进行发电机测试时&#xff0c;需要关注一些常见的参数和规格&#xff0c;以确保其安全、高效和可靠的运行。以下是一些需要关注的发电机测试参数和规格&#xff1a; 1. 电压&#xff1a;发电机的输出电压是衡量其性能的重要指标…

车用传感器频繁损坏的原因及解决方案

1.车用传感器频繁损坏的原因&#xff1f; 雷卯EMC小哥&#xff0c;在汽车客户做整改中发现&#xff0c;车用传感器频繁损坏&#xff0c;主要的共同原因&#xff1a;不稳定的电压。 在车辆工作过程中&#xff0c;电压波动是无法避免的。这些波动可能源自发动机的启动、发电机的…

RISC-V SoC + AI | 在全志 D1「哪吒」开发板上,跑个 ncnn 神经网络推理框架的 demo

引言 D1 是全志科技首款基于 RISC-V 指令集的 SoC&#xff0c;主核是来自阿里平头哥的 64 位的 玄铁 C906。「哪吒」开发板 是全志在线基于全志科技 D1 芯片定制的 AIoT 开发板&#xff0c;是目前还比较罕见的使用 RISC-V SoC 且可运行 GNU/Linux 操作系统的可量产开发板。 n…

进阶数据结构 BTree 的插入与删除操作实现

在数据库系统和文件系统中&#xff0c;高效的数据组织与管理是关键之一。B-Tree&#xff08;Balanced Tree&#xff09;作为一种平衡搜索树结构&#xff0c;在这一领域发挥着重要作用。本文详细探讨了 B-Tree 的基本概念以及对其进行插入与删除操作的实现&#xff0c;旨在帮助读…

【嵌入式学习】QT-Day4-Qt基础

简单实现闹钟播报&#xff0c;设置时间&#xff0c;当系统时间与设置时间相同时播报语音5次&#xff0c;然后停止。如果设置时间小于当前系统时间&#xff0c;则弹出消息提示框&#xff0c;并清空输入框。 #include "my_clock.h" #include "ui_my_clock.h&quo…

面试redis篇-08数据淘汰策略

原理 当Redis中的内存不够用时,此时在向Redis中添加新的key,那么Redis就会按照某一种规则将内存中的数据删除掉,这种数据的删除规则被称之为内存的淘汰策略。 Redis支持8种不同策略来选择要删除的key: noeviction: 不淘汰任何key,但是内存满时不允许写入新数据,默认就是…

【教程】 iOS混淆加固原理篇

目录 摘要 引言 正文 1. 加固的缘由 2. 编译过程 3. 加固类型 1) 字符串混淆 2) 类名、方法名混淆 3) 程序结构混淆加密 4) 反调试、反注入等一些主动保护策略 4. 逆向工具 5. OLLVM 6. IPA guard 7. 代码虚拟化 总结 摘要 本文介绍了iOS应用程序混淆加固的缘由…