深度优先遍历与广度优先遍历

深度优先遍历不断深入图中并在栈中保存了所有分叉的顶点;广度优先遍历则像扇面一般扫描图,用一个队列保存访问过的最前端的顶点。深度遍历的方式是寻找离起点更远的顶点,只在碰到死胡同时才访问进出的顶点,广度遍历则会首先覆盖起点附近的顶点,只在临近的顶点都被访问完后,才去访问更远的顶点。
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实现深度优先遍历和广度优先遍历
图(一):无向图的深度优先遍历、广度优先遍历及连通分量

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