數據結構中,樹或圖有兩種遍歷方法,BFS--廣度優先搜索、DFS--深度優先搜索。
DOM樹也是一種樹的實現。
如果我們有如下一顆DOM樹,如果我們想要遍歷它的每一個節點,應該怎么做呢。
<div id="app">
<div id="header">
<div id="logo"></div>
<div id="menu"></div>
</div>
<div id="content">
<div id="article">
<div id="para1"></div>
<div id="para2"></div>
<div id="para3"></div>
</div>
</div>
</div>
DFS
function DFS(node, cb) {
let deep = 1;
DFSdom(node,deep,cb)
}
function DFSdom(node, deep, cb) {
if(!node)
return;
cb(node,deep)
if(!node.childNodes.length) {
return;
}
deep++;
Array.from(node.childNodes).forEach(item => DFSdom(item,deep,cb))
}
使用:
DFS(document.getElementById("app"),function (node,deep) {
if(node.nodeType == 3) // 排除文本節點
return
console.log(node,deep);
})
打印結果:
Object {node: div#app, deep: 1}
Object {node: div#header, deep: 2}
Object {node: div#logo, deep: 3}
Object {node: div#menu, deep: 3}
Object {node: div#content, deep: 2}
Object {node: div#article, deep: 3}
Object {node: div#para1, deep: 4}
Object {node: div#para2, deep: 4}
Object {node: div#para3, deep: 4}
DFS的實現是利用遞歸,遞歸實現是利用堆棧。所以使用DFS有爆棧的風險。
BFS
function BFS(node,cb) {
if(!node)
return;
var queue = [{
node: node,
depth: 1
}]
while(queue.length) {
var current = queue.shift();
cb(current)
current.node.childNodes.length && Array.from(current.node.childNodes).forEach(item => {
queue.push({
node: item,
depth: current.depth + 1
})
})
}
}
使用:
BFS(document.getElementById("app"),function (node) {
if(node.node.nodeType == 3) // 排除文本節點
return
console.log(node);
})
打印結果:
Object {node: div#app, depth: 1}
Object {node: div#header, depth: 2}
Object {node: div#content, depth: 2}
Object {node: div#logo, depth: 3}
Object {node: div#menu, depth: 3}
Object {node: div#article, depth: 3}
Object {node: div#para1, depth: 4}
Object {node: div#para2, depth: 4}
Object {node: div#para3, depth: 4}
BFS的實現是利用隊列。