深度優先遍歷與廣度優先遍歷

深度優先遍歷不斷深入圖中並在棧中保存了所有分叉的頂點;廣度優先遍歷則像扇面一般掃描圖,用一個隊列保存訪問過的最前端的頂點。深度遍歷的方式是尋找離起點更遠的頂點,只在碰到死衚衕時才訪問進出的頂點,廣度遍歷則會首先覆蓋起點附近的頂點,只在臨近的頂點都被訪問完後,纔去訪問更遠的頂點。
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實現深度優先遍歷和廣度優先遍歷
圖(一):無向圖的深度優先遍歷、廣度優先遍歷及連通分量

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章