-
Notifications
You must be signed in to change notification settings - Fork 3.3k
Open
Labels
Description
第五题问的是深度优先遍历和广度优先遍历,我是从dom节点的遍历来理解这个问题的
html代码
我将用深度优先遍历和广度优先遍历对这个dom树进行查找
深度优先遍历
深度优先遍历DFS 与树的先序遍历比较类似。
假设初始状态是图中所有顶点均未被访问,则从某个顶点v出发,首先访问该顶点然后依次从它的各个未被访问的邻接点出发深度优先搜索遍历图,直至图中所有和v有路径相通的顶点都被访问到。若此时尚有其他顶点未被访问到,则另选一个未被访问的顶点作起始点,重复上述过程,直至图中所有顶点都被访问到为止。
/*深度优先遍历三种方式*/
let deepTraversal1 = (node, nodeList = []) => {
if (node !== null) {
nodeList.push(node)
let children = node.children
for (let i = 0; i < children.length; i++) {
deepTraversal1(children[i], nodeList)
}
}
return nodeList
}
let deepTraversal2 = (node) => {
let nodes = []
if (node !== null) {
nodes.push(node)
let children = node.children
for (let i = 0; i < children.length; i++) {
nodes = nodes.concat(deepTraversal2(children[i]))
}
}
return nodes
}
// 非递归
let deepTraversal3 = (node) => {
let stack = []
let nodes = []
if (node) {
// 推入当前处理的node
stack.push(node)
while (stack.length) {
let item = stack.pop()
let children = item.children
nodes.push(item)
// node = [] stack = [parent]
// node = [parent] stack = [child3,child2,child1]
// node = [parent, child1] stack = [child3,child2,child1-2,child1-1]
// node = [parent, child1-1] stack = [child3,child2,child1-2]
for (let i = children.length - 1; i >= 0; i--) {
stack.push(children[i])
}
}
}
return nodes
}
输出结果
广度优先遍历
广度优先遍历 BFS
从图中某顶点v出发,在访问了v之后依次访问v的各个未曾访问过的邻接点,然后分别从这些邻接点出发依次访问它们的邻接点,并使得“先被访问的顶点的邻接点先于后被访问的顶点的邻接点被访问,直至图中所有已被访问的顶点的邻接点都被访问到。 如果此时图中尚有顶点未被访问,则需要另选一个未曾被访问过的顶点作为新的起始点,重复上述过程,直至图中所有顶点都被访问到为止。
let widthTraversal2 = (node) => {
let nodes = []
let stack = []
if (node) {
stack.push(node)
while (stack.length) {
let item = stack.shift()
let children = item.children
nodes.push(item)
// 队列,先进先出
// nodes = [] stack = [parent]
// nodes = [parent] stack = [child1,child2,child3]
// nodes = [parent, child1] stack = [child2,child3,child1-1,child1-2]
// nodes = [parent,child1,child2]
for (let i = 0; i < children.length; i++) {
stack.push(children[i])
}
}
}
return nodes
}
输出结果
ps
仅个人理解,如果有错欢迎大家指出批评,一起进步
machangzhi, shiiiiiiji, atheist1, HadeAs, Jvid and 244 moreddzy and pengwenbohuyaocode, chenyuhuan1, YangyanGZMY, zhoufengcheck, arcsin1 and 9 morehuyaocode, mongonice, dogfeeling, chenyuhuan1, YangyanGZMY and 8 morehuyaocode, sunkeai, chenyuhuan1, YangyanGZMY, c1026287787 and 12 moreylinwind, huyaocode, abner-forever, Alice-Qian, chenyuhuan1 and 15 moreMaxPeak, huyaocode, deleteName, wyj1242, Xu-Angel and 11 more
Metadata
Metadata
Assignees
Labels
Type
Projects
Milestone
Relationships
Development
Select code repository
Activity
shiiiiiiji commentedon Feb 13, 2019
概念上我觉得没啥问题,具体在业务上有啥应用的地方吗(尤其是前端)?
2.14补充
对象的深拷贝
sisterAn commentedon Feb 16, 2019
图
图是一种复杂的非线性结构,它由边(边Edge)和点(顶点Vertex)组成。一条边连接的两个点称为相邻顶点。
图分为:
本文探讨的是无向图
图的表示
图的表示一般有以下两种:
arr[i][j] = 1
表示节点 i 与节点 j 之间有边,arr[i][j] = 0
表示节点 i 与节点 j 之间没有边创建图
下面声明图类,Vertex 用数组结构表示,Edge 用 map结构表示
测试:
测试成功
图的遍历
两种遍历算法:
深度优先遍历(DFS)
深度优先遍历(Depth-First-Search),是搜索算法的一种,它沿着树的深度遍历树的节点,尽可能深地搜索树的分支。当节点v的所有边都已被探寻过,将回溯到发现节点v的那条边的起始节点。这一过程一直进行到已探寻源节点到其他所有节点为止,如果还有未被发现的节点,则选择其中一个未被发现的节点为源节点并重复以上操作,直到所有节点都被探寻完成。
简单的说,DFS就是从图中的一个节点开始追溯,直到最后一个节点,然后回溯,继续追溯下一条路径,直到到达所有的节点,如此往复,直到没有路径为止。
DFS 可以产生相应图的拓扑排序表,利用拓扑排序表可以解决很多问题,例如最大路径问题。一般用堆数据结构来辅助实现DFS算法。
注意:深度DFS属于盲目搜索,无法保证搜索到的路径为最短路径,也不是在搜索特定的路径,而是通过搜索来查看图中有哪些路径可以选择。
步骤:
实现:
测试:
测试成功
广度优先遍历(BFS)
广度优先遍历(Breadth-First-Search)是从根节点开始,沿着图的宽度遍历节点,如果所有节点均被访问过,则算法终止,BFS 同样属于盲目搜索,一般用队列数据结构来辅助实现BFS
BFS从一个节点开始,尝试访问尽可能靠近它的目标节点。本质上这种遍历在图上是逐层移动的,首先检查最靠近第一个节点的层,再逐渐向下移动到离起始节点最远的层
步骤:
实现:
测试:
测试成功
本文始发于我的博客:深度优先遍历与广度优先遍历
kscript commentedon Feb 19, 2019
前端确实很少涉及算法。 这个我也只在做小游戏的时候有用到过
vivatoviva commentedon Feb 19, 2019
caihg commentedon Feb 19, 2019
@atheist1
非递归版的 deepTraversal3 实际上是广度优先的
Ray-56 commentedon Mar 4, 2019
@caihg 我也是这样想的
BaconZhang commentedon Mar 11, 2019
这其实是和公司的具体业务相关的,我们公司把在业务层背后抽象了一套树形结构的领域对象模型,整个项目里少不了折腾树的递归,这时候发现熟练掌握深度遍历和广度遍历就十分有用了。
rccoder commentedon Mar 31, 2019
@atheist1 宽搜还是写 queue 吧,stack 歧义太严重了
[-]关于第五题我的一些见解[/-][+]第五题:深度优先遍历和广度优先遍历[/+]iamwelk commentedon Apr 8, 2019
这个字打错了吧
MaxPeak commentedon Apr 22, 2019
写得非常好了,我之前也了解过这两个东西,@atheist1 ,代码通俗易懂,答案简单直观,非常棒
[-]第五题:深度优先遍历和广度优先遍历[/-][+]第 5 题:介绍下深度优先遍历和广度优先遍历,如何实现?[/+]CBGhaha commentedon Apr 29, 2019
generator +Interator接口实现深度遍历
21 remaining items
SnailOwO commentedon Jun 19, 2020
leon-230224 commentedon Jun 30, 2020
第二个广度和第一个不是一样的嘛
i7eo commentedon Aug 22, 2020
没毛病的,循环是倒序。就是深度
yanrongbao commentedon Oct 15, 2020
获取项不一样 一个用到了pop 一个用shift
zhimng commentedon Oct 26, 2020
DFS 可以用在查找两个 dom 节点的相同祖先节点
hurongju commentedon Feb 4, 2021
数组扁平化
wangrx-jerry commentedon Feb 26, 2021
chivalrousAlisa commentedon Oct 26, 2021
我在业务中有用到过:
1、富文本“一键排版”
2、树形组件,拖动排序,数据递归处理等
ehxie commentedon Jan 22, 2022
附上结果图:
guaziing commentedon Sep 13, 2022
这个打印出来是深度优先哟,实践一下再说,别误导了
kingforever commentedon Sep 13, 2022
uaoin commentedon Sep 22, 2022
给sisterAn的回复加上了一些配图,方便理解
图
图是一种复杂的非线性结构,他由边(Edge)和点(Vertex)组成.
一条边链接的两个点称为相邻顶点.
图分为:
本文探讨的是无向图
图的表示
图的表示一般有以下两种:
arr[i][j] = 1
表示节点 i 与节点 j 之间有边,arr[i][j] = 0
表示节点 i 与节点 j 之间没有边. (有向图使用邻接矩阵空间复杂度较大,0是没有用的信息)创建图
Vertex用数组结构表示,Edge用[[Set、Map、WeakSet 和 WeakMap 的区别#字典 Map|map]]结构表示(因为“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。)
测试:
测试成功
图的遍历
两种遍历算法:
深度优先遍历(DFS)
深度优先遍历(Depth-First-Search),是搜索算法的一种,它沿着树的深度遍历树的节点,尽可能深地搜索树的分支。当节点v的所有边都已被探寻过,将回溯到发现节点v的那条边的起始节点。这一过程一直进行到已探寻源节点到其他所有节点为止,如果还有未被发现的节点,则选择其中一个未被发现的节点为源节点并重复以上操作,直到所有节点都被探寻完成。
简单的说,DFS就是从图中的一个节点开始追溯,直到最后一个节点,然后回溯,继续追溯下一条路径,直到到达所有的节点,如此往复,直到没有路径为止。
DFS 可以产生相应图的拓扑排序表,利用拓扑排序表可以解决很多问题,例如最大路径问题。一般用堆数据结构来辅助实现DFS算法。
注意:深度DFS属于盲目搜索,无法保证搜索到的路径为最短路径,也不是在搜索特定的路径,而是通过搜索来查看图中有哪些路径可以选择。
步骤
实现
测试
广度优先遍历(BFS)
广度优先遍历(Breadth-First-Search)是从根节点开始,沿着图的宽度遍历节点,如果所有节点均被访问过,则算法终止,BFS 同样属于盲目搜索,一般用队列数据结构来辅助实现BFS
BFS从一个节点开始,尝试访问尽可能靠近它的目标节点。本质上这种遍历在图上是逐层移动的,首先检查最靠近第一个节点的层,再逐渐向下移动到离起始节点最远的层
步骤
实现
测试
EOS1O commentedon Nov 7, 2022
在做后台管理系统的时候,遇到了这样的需求:左侧做成无限级目录,右侧上方面包屑要显示对应的路径。
这个时候有两种方案:
1.让后端提供一个接口,直接将路径array返回给前端
2.让后端在每一个目录node中加上其对应的father node的id。前端自己进行处理,处理方法如下:
kingforever commentedon Nov 7, 2022
uaoin commentedon Nov 10, 2022
菜狗子前端分享一下自己的总结,如有不足欢迎指出!
dfs和bfs
导览:
dfs:递归和栈
bfs:队列
图
图的构造函数和方法
图的dfs
此外还可以使用入栈出栈的方法,见下文
图的bfs
while
循环,当队列为空时则结束遍历shift
)改为栈(pop
),就会变为dfs树
DOM树长这个样子:
要求:按顺序打印出遍历的元素。
DOM节点的dfs
递归
栈
DOM节点的bfs
队列
栈与队列在dfs和bfs时的区别
使用栈和队列时需要一个起始点,进行分解(对于图来说就是分解为相邻的点)