先画个树,然后解释 何为深度, 何为广度
第一层 子集
|
__________________________
| |
第二层1 子集 第二层2 子集
| |
-----------------
第三层11,子集 第三层12
|
第四层111
图就不画太复杂了,最高四层的结构,如果换成html的形式的话可以理解成
<div>------第一层
<ul>----------第二层1
<li> -----------第三层 11
<span></span> -----------第四层 111
</li>
<li>---------------第三层 12
</li>
</ul>
<p></p> ------------第一层2
<div>
深度遍历,就是 从 第一层开始 -》 1 -》 11 -》111 -》 12 -》 2
这个意思就是,如果有下一级优先探索下一级的,没有了话,再去探索兄弟层级(以此类推)
就是做一道菜,需要菜和调料,调料是需要调制的,比如调料需要鸡汁和糖,鸡汁又需要调制,那么 正常流程 就是 ,
1、开始做菜 -》 开始调料 -》 鸡汁 -》调制鸡汁的材料
2、等这些弄完了,再去加糖 ,完成调料步骤
3、糖加完了,再去切菜,完成做菜步骤
这个就是一个深度的过程
而广度遍历则相反, 顺序应该是 -> 1-> 2 -> 11 -> 12 -> 111
意思就是有兄弟层级优先解析兄弟层级,然后解析下一层级
广度比较符合正常人的思维,就像复习的时候,
1.先把整本书捋一遍,然后画重点,
2.捋完之后看重点,重点内容里面有一些具体时间,再整理出来,
3.最后重点背诵时间
广度遍历需要手动去终结(判断还有没有整理内容了)
根据js单线程的原理,深度很好实现,因为循环递归默认就是深度遍历
把刚刚的图 写成一个数组
const arr = [
{
name: '1',
childrens: [
{
name: '11',
childrens: [
{
name: '111'
}
]
},
{
name: '12'
}
]
},
{
name: '2'
}
]
我多加了一些换行,方便看清楚
深度遍历
function check(nodeArr) {
nodeArr.forEach(node => {
console.log(node.name)
if(node.childrens) {
check(node.childrens)
}
})
}
check(arr) //
1
11
111
12
2
这段代码很好理解,如果有子集,将子集和父集做同样处理,或者说,作为一个新的参数给check这个方法。
广度遍历
广度遍历的话需要一个容器去记录子集,等此层级的兄弟集处理完成,再去处理子集,子集的处理也以此类推
先上代码
function checkN(nodeX) {
var node_ = []; // 用来存储子集
nodeX.forEach(node => {
console.log(node.name);
if(node.childrens) {
node_ = [...node_, ...node.childrens];
}
})
if(node_[0])
checkN(node_);
}
checkN(arr) //
1
2
11
12
111
具体内容就这些了,这两个算法我刚刚自己想着写的,不知道和一些比较正式的文章算法是不是略有出入,我也懒得去看了
应一个大佬朋友,也是我高中同学的要求,写了一个非递归版本
这个是深度优先的.....
function check_(nodeArr) {
let processList = nodeArr;
while(processList[0]) {
const a = processList.shift();
if(a.childrens)
processList = [...a.childrens, ...processList];
console.log(a.name);
}
}
check_(arr);//
1
11
111
12
2
这个是广度优先的
function checkX_(nodeArr) {
let processList = nodeArr;
while(processList[0]) {
const a = processList.shift();
if(a.childrens) {
processList = [...processList,...a.childrens];
}
console.log(a.name);
}
}
checkX_(arr);//
1
2
11
12
111
这两个代码的相似度几乎是百分之九十,唯一的区别就是先进先出(广度优先),和先进后出(深度优先)
先进先出的话,后来者就排到其后面,先进后出,后来者就排到其前面
那么唯一的区别就是 processList = [...a.childrens, ...processList]; 还是 processList = [...processList,...a.childrens];
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。