遍历树/图时,广度优先和深度之间的区别首先是什么?任何编码或伪代码都很棒。
答案 0 :(得分:265)
这两个术语区分了两种不同的树木行走方式。
展示差异可能最简单。考虑树:
A
/ \
B C
/ / \
D E F
深度第一次遍历将按此顺序访问节点
A, B, D, C, E, F
请注意,在继续前进之前,您将一路向下。
广度首次遍历将按此顺序访问节点
A, B, C, D, E, F
这里我们一直在跨每个级别工作,然后再下台。
(请注意,遍历顺序存在一些歧义,我在树的每个级别都保持“阅读”顺序。在任何一种情况下,我都可以在C之前或之后到达B,同样我可以在F之前或之后到达E.这可能或不重要,取决于您的申请......)
使用伪代码可以实现两种遍历:
Store the root node in Container
While (there are nodes in Container)
N = Get the "next" node from Container
Store all the children of N in Container
Do some work on N
两个遍历顺序之间的区别在于Container
的选择。
递归实现看起来像
ProcessNode(Node)
Work on the payload Node
Foreach child of Node
ProcessNode(child)
/* Alternate time to work on the payload Node (see below) */
当您到达没有子节点的节点时,递归结束,因此保证结束 有限的非循环图。
此时,我还是有点作弊。稍微聪明一点,你也可以按顺序继续节点:
D, B, E, F, C, A
这是深度优先的变体,我不会在每个节点上完成工作,直到我走回树上。然而,我已经访问了更高的节点,以便找到他们的孩子。
这种遍历在递归实现中相当自然(使用上面的“备用时间”行而不是第一个“工作”行),如果使用显式堆栈,则太难,但是我会把它留作练习。
答案 1 :(得分:71)
这张图片可以让您了解使用广度和深度这些词语的上下文。
深度优先搜索算法就好像它想要远离它一样 从起点开始尽快。
它通常使用Stack
来记住它到达死胡同时应该去的地方。
要遵循的规则:将第一个顶点A推到Stack
Java代码:
public void searchDepthFirst() {
// Begin at vertex 0 (A)
vertexList[0].wasVisited = true;
displayVertex(0);
stack.push(0);
while (!stack.isEmpty()) {
int adjacentVertex = getAdjacentUnvisitedVertex(stack.peek());
// If no such vertex
if (adjacentVertex == -1) {
stack.pop();
} else {
vertexList[adjacentVertex].wasVisited = true;
// Do something
stack.push(adjacentVertex);
}
}
// Stack is empty, so we're done, reset flags
for (int j = 0; j < nVerts; j++)
vertexList[j].wasVisited = false;
}
Applications:深度优先搜索通常用于模拟游戏(以及现实世界中类似游戏的情况)。在典型的游戏中,您可以选择几种可能的操作之一。每个选择都会带来进一步的选择,每个选择都会导致进一步的选择,等等,形成一个不断扩展的树形图表。
Queue
。Java代码:
public void searchBreadthFirst() {
vertexList[0].wasVisited = true;
displayVertex(0);
queue.insert(0);
int v2;
while (!queue.isEmpty()) {
int v1 = queue.remove();
// Until it has no unvisited neighbors, get one
while ((v2 = getAdjUnvisitedVertex(v1)) != -1) {
vertexList[v2].wasVisited = true;
// Do something
queue.insert(v2);
}
}
// Queue is empty, so we're done, reset flags
for (int j = 0; j < nVerts; j++)
vertexList[j].wasVisited = false;
}
Applications:广度优先搜索首先找到距离起点一个边的所有顶点,然后找到两个边距离的所有顶点,依此类推。如果您尝试找到从起始顶点到给定顶点的最短路径,这将非常有用。
希望这应该足以理解广度优先和深度优先搜索。为了进一步阅读,我将推荐Robert Lafore的优秀数据结构书中的图表章节。
答案 2 :(得分:3)
鉴于这个二叉树:
广度优先遍历:
从左到右遍历每个级别。
&#34;我G,我的孩子是D和我,我的孙子是B,E,H和K,他们的孙子是A,C,F&#34;
- Level 1: G
- Level 2: D, I
- Level 3: B, E, H, K
- Level 4: A, C, F
Order Searched: G, D, I, B, E, H, K, A, C, F
深度优先遍历:
遍历不是一次完成整个级别。相反,遍历首先潜入树的DEPTH(从根到叶)。但是,它比简单的上下都复杂一点。
有三种方法:
1) PREORDER: ROOT, LEFT, RIGHT.
You need to think of this as a recursive process:
Grab the Root. (G)
Then Check the Left. (It's a tree)
Grab the Root of the Left. (D)
Then Check the Left of D. (It's a tree)
Grab the Root of the Left (B)
Then Check the Left of B. (A)
Check the Right of B. (C, and it's a leaf node. Finish B tree. Continue D tree)
Check the Right of D. (It's a tree)
Grab the Root. (E)
Check the Left of E. (Nothing)
Check the Right of E. (F, Finish D Tree. Move back to G Tree)
Check the Right of G. (It's a tree)
Grab the Root of I Tree. (I)
Check the Left. (H, it's a leaf.)
Check the Right. (K, it's a leaf. Finish G tree)
DONE: G, D, B, A, C, E, F, I, H, K
2) INORDER: LEFT, ROOT, RIGHT
Where the root is "in" or between the left and right child node.
Check the Left of the G Tree. (It's a D Tree)
Check the Left of the D Tree. (It's a B Tree)
Check the Left of the B Tree. (A)
Check the Root of the B Tree (B)
Check the Right of the B Tree (C, finished B Tree!)
Check the Right of the D Tree (It's a E Tree)
Check the Left of the E Tree. (Nothing)
Check the Right of the E Tree. (F, it's a leaf. Finish E Tree. Finish D Tree)...
Onwards until...
DONE: A, B, C, D, E, F, G, H, I, K
3) POSTORDER:
LEFT, RIGHT, ROOT
DONE: A, C, B, F, E, D, H, K, I, G
用法(又名,我们为什么关心):
我非常喜欢这种简单的Quora对深度优先遍历方法的解释以及它们如何被普遍使用:
&#34;有序遍历将打印值[为了BST(二叉搜索树)]&#34;
&#34;预订遍历用于创建[二叉搜索树]的副本。&#34;
&#34;后序遍历用于删除[二叉搜索树]。&#34;
https://www.quora.com/What-is-the-use-of-pre-order-and-post-order-traversal-of-binary-trees-in-computing
答案 3 :(得分:2)
我认为以一种方式编写它们会很有意思,只有通过切换某些代码行才会给你一个算法或另一个算法,这样你就会发现你的dillema并不像看起来那样强大起初。
我个人喜欢将BFS解释为淹没景观:低海拔地区将首先被淹没,然后才会出现高海拔地区。如果你把地形书中的景观高度想象为等值线,很容易看出BFS同时填充同一等值线下的所有区域,就像物理学一样。因此,将高度解释为距离或缩放成本可以非常直观地了解算法。
考虑到这一点,您可以轻松地调整广度优先搜索背后的想法,以便轻松找到最小生成树,最短路径以及许多其他最小化算法。
我还没有看到任何关于DFS的直观解释(只有关于迷宫的标准解释,但它不像BFS那样强大并且泛滥),所以对我而言,似乎BFS似乎更好地与所描述的物理现象相关联在上面,DFS与理性系统中的选择dillema(即人或计算机决定在国际象棋比赛中进行哪种移动或走出迷宫)的关联更好。
所以,对我来说,现实生活中哪种自然现象与其传播模型(横向)最匹配的谎言之间存在差异。