数据结构—图深度优先遍历和广度优先遍历

207 阅读1分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

图的分类

有向图

directed_acyclic.png

无向图

undirected_graph.png

有权重图

weight.png

有了之前树的深度优先遍历和广度优先遍历的基础。今天要介绍图深度优先遍历有容易多了,比较类似,对于深度优先通常用栈,对于广度优先通常用到队列。

graph_traversal_001.png

我们构建以一个图,用邻边对应到一个结点

const graph = {
    a:['c','b'],
    b:['d'],
    c:['e'],
    d:['f'],
    e:[],
    f:[]
}

graph_traversal_007.png

创建一个栈(stack),然后将以结点压入到栈中。

graph_traversal_005.png

graph_traversal_003.png

然后判断是否栈是否为空,将栈顶的结点出栈后,同时将结点的邻居结点压入到栈,然后进入下一次迭代

graph_traversal_002.png

每一次迭代,判断是否栈为空,如果为空就退出迭代,不为空这先将栈顶的结点出栈,然后在将该结点的邻接结点压入到栈,重复以上的迭代。

深度优先遍历

迭代方式

const depthFirstPrint = (graph,source)=>{
    const stack = [source];

    while(stack.length > 0){
        const current = stack.pop();
        console.log(current)
        for(let neighboer of graph[current]){
            stack.push(neighboer)
        }
    }
}

const graph = {
    a:['c','b'],
    b:['d'],
    c:['e'],
    d:['f'],
    e:[],
    f:[]
}

depthFirstPrint(graph,'a');

递归方式

const depthFirstPrintWithRecursive = (graph, source) => {
    console.log(source);
    for( let neighbor of graph[source]){
        depthFirstPrintWithRecursive(graph,neighbor)
    }
}

const graph = {
    a:['b','c'],
    b:['d'],
    c:['e'],
    d:['f'],
    e:[],
    f:[]
}

depthFirstPrintWithRecursive(graph,'a');

广度优先遍历

迭代方式

const breathFirstPrint = (graph,source)=>{
    const queue = [ source ];
    while(queue.length > 0){
        const current = queue.shift();
        console.log(current);
        for(let neighbor of graph[current]){
            queue.push(neighbor)
        }
    }
}

const graph = {
    a:['c','b'],
    b:['d'],
    c:['e'],
    d:['f'],
    e:[],
    f:[]
}

breathFirstPrint(graph,'a');