深度優先遍歷不斷深入圖中並在棧中保存了所有分叉的頂點;廣度優先遍歷則像扇面一般掃描圖,用一個隊列保存訪問過的最前端的頂點。深度遍歷的方式是尋找離起點更遠的頂點,只在碰到死衚衕時才訪問進出的頂點,廣度遍歷則會首先覆蓋起點附近的頂點,只在臨近的頂點都被訪問完後,纔去訪問更遠的頂點。
const data = [
{
name: 'a',
children: [
{ name: 'b', children: [{ name: 'e' }] },
{ name: 'c', children: [{ name: 'f' }] },
{ name: 'd', children: [{ name: 'g' }] },
],
},
{
name: 'a2',
children: [
{ name: 'b2', children: [{ name: 'e2' }] },
{ name: 'c2', children: [{ name: 'f2' }] },
{ name: 'd2', children: [{ name: 'g2' }] },
],
}
]
// 深度遍歷, 使用遞歸
// "a,b,e,c,f,d,g,a2,b2,e2,c2,f2,d2,g2"
function getName(data) {
const result = [];
data.forEach(item => {
const map = data => {
result.push(data.name);
data.children && data.children.forEach(child => map(child));
}
map(item);
});
return result.join(',');
}
// 廣度遍歷, 創建一個執行隊列,當隊列爲空的時候則結束
function getNameBreadth(data) {
let result = [];
let queue = data;
while(queue.length > 0) {
[...queue].forEach(child => {
queue.shift();
result.push(child.name);
child.children && (queue.push(...child.children));
})
}
return result.join(',');
}
getNameBreadth(data);
// 深度優先搜索就是自上而下的遍歷搜索
// 廣度優先則是逐層遍歷
// 深度優先不需要記住所有的節點,所以佔用空間小,而廣度優先需要記錄所有的節點,佔用空間大
// 深度優先有回溯的操作(沒有路走路了需要回頭), 所以相對時間長一點
// 深度優先採用的是堆棧的形式,即先進後出
// 廣度優先則採用隊列的形式,即先進先出
深度優先遍歷常用目錄文件的遍歷
虛擬DOM說到底只是一顆樹形結構,對於樹的遍歷我們知道有深度遍歷和廣度遍歷
深度遍歷需要棧結構,可以通過遞歸(內核維護調用棧)的方式實現,也可以採用人爲構造棧,然後循環棧完成深度遍歷。通常深度優先搜索法不全部保留結點,擴展完的結點從棧中彈出刪去,這樣,在棧中存儲的結點數就是深度值,因此它佔用空間較少。
廣度遍歷則採用隊列的方式實現,由於廣度優先是按照樹的層級來遍歷的,在遍歷某層的時候需要將下一層的數據推進隊列裏面,所以隊列的長度通常會比樹的寬度還要寬。
參考文章:
js實現深度優先遍歷和廣度優先遍歷
圖(一):無向圖的深度優先遍歷、廣度優先遍歷及連通分量