ACM金牌带你零基础直达C语言精通-课程资料
本笔记属于船说系列课程之一,课程链接:
你也可以选择购买『船说系列课程-年度会员』产品『船票』,畅享一年内无限制学习已上线的所有船说系列课程:船票购买入口https://www.bilibili.com/cheese/pages/packageCourseDetail?productId=598
做题网站OJ:HZOJ - Online Judge
Leetcode :力扣 (LeetCode) 全球极客挚爱的技术成长平台
树-广度优先遍历
广度优先遍历(BFS) :
是一种图遍历算法,用于在一个图或树数据结构中逐层地遍历节点,从根节点开始,先访问所有相邻的节点,然后再逐层向下访问相邻的节点。这个算法通常使用队列来实现,以确保按照节点的距离顺序访问它们。
在执行广度优先遍历时,首先访问起始节点,然后将其所有未访问的相邻节点加入队列。接着,从队列中取出下一个节点,访问其未访问的相邻节点,并将这些相邻节点加入队列。这个过程重复进行,直到队列为空为止,所有节点都被访问过。
广度优先遍历的一个重要应用是在图中寻找最短路径。由于它按照节点距离的顺序进行遍历,当搜索到目标节点时,它所经过的路径就是最短路径之一。
总的来说,广度优先遍历是一种有效的图遍历算法,适用于寻找最短路径以及其他需要逐层访问节点的场景。
广度优先遍历的作用:
- 最短路径搜索:BFS 通常用于在无权图或权重相同的图中查找最短路径,因为它首先搜索到的路径往往是最短的。
- 最小生成树:BFS 可以用于生成最小生成树,例如在 Prim 算法中,通过不断扩展当前的树来选择最小权重的边。
- 连通性检测:BFS 也可以用于检测图的连通性,与 DFS 类似,它可以用于确定一个图是否是连通图。
- 网络广播:在网络中,BFS 可以用于广播消息或搜索特定的节点。
如下这张图,利用广度优先算法进行对它遍历
以P1作为顶点进行开始遍历,这里需要利用到队列进行遍历:
先将P1进行入队
然后再对队列的头元素进行判断,判断它相邻或者指向的节点,那么可以从图中判断有P5和P2这两个节点,然后对这两个节点进行入队操作,并且再将P1出队
然后同样的操作,进行对P2相邻节点判断,然后进行入队操作,和对头部元素的出队操作:
注意点:然后通过相同的操作,遍历到P4节点时会发现P3已经被遍历过了,那么再写程序中就需要进行去判断,遍历节点的相邻节点时,该节点是否被遍历过:
最终遍历结果就是:
这个过程你可以理解像水一样,当再P1中倒入水,那么P1会流向P2和P5,而P2和P5又会流向他们相邻的节点,最终水会流到每一个节点当中。
这就是广度优先遍历的一个理解过程。
理解了广度优先遍历,再去对树进行广度优先遍历,那不手到擒来:
过程就省略了:
可以发现:
再遍历的过程中,是一层一层进行去遍历的,在遍历树中广度优先遍历也层序遍历,在对树的每一层进行需要去操作时,可以利用广度优先遍历。
树-深度优先遍历
深度优先遍历:
深度优先遍历(DFS)是一种图遍历算法,它从起始节点开始,沿着图的深度尽可能远地搜索,直到到达最深的节点,然后再回溯到上一个节点,继续搜索其他路径。这个过程会一直进行下去,直到所有节点都被访问过为止。
DFS 通常使用递归或者栈来实现。在执行深度优先遍历时,从起始节点开始,首先访问它,并标记为已访问。然后,对于当前节点的每个未访问的相邻节点,递归地对其进行深度优先遍历。这个过程会一直持续,直到到达一个没有未访问相邻节点的节点,然后回溯到上一个节点,继续搜索其他路径,直到所有节点都被访问过。
深度优先遍历的一个重要应用是在图中寻找路径或者解决连通性问题。由于它沿着图的深度进行搜索,因此更适合于寻找一条路径直到底部,然后再回溯的情况。
深度优先遍历可以称为不撞南墙不回头,为什么因为它遍历每条路时会一直走到不能走了然后在回头,也就是一个一个回到之前节点或者递归的上一层(也就是回溯)。
深度优先遍历的作用:
- 寻找路径:DFS 可以用于在图或树中查找路径,特别是当我们希望沿着一条路径尽可能远地搜索时。
- 连通性检测:DFS 可以用于检测图中的连通性,例如确定一个图是否是连通图(每两个节点之间都存在路径)。
- 拓扑排序:DFS 可以用于拓扑排序,即对有向无环图进行排序,使得图中的所有节点按照一定的顺序排列。
- 判断环路:DFS 可以用于检测图中是否存在环路,通过在遍历过程中记录路径上的节点,如果在搜索的过程中发现某个节点已经在路径上,则存在环路。
例子:
这里我用的方法是栈,利用递归也可以进行深度优先遍历:
先对1,进行入栈:
然后对该节点的左子树进行访问,一直访问直到他没有左子树,那么下一个入栈元素就应该是2:
继续访问左子树:
现在没有左子树了,又因为要一直往下走直到撞南墙才回头,那么就应该访问右子树,右子树也没有,那么就该回头了,对元素4进行出栈,然后遍历栈顶元素2的右子树:
然后通过同样的思路最终遍历完成树的每一个节点,最终的遍历结果:
总结
对于广度优先和深度优先遍历,不仅仅是对树的进行遍历,对于它们作用的理解,可以带入到相应的场景进行对它们的使用。