算法学习记录(十三)

100 阅读1分钟

问:

  1. 图的广度优先遍历和深度优先遍历
  2. 拓扑排序

解:

  1. 广度遍历用哈希表存值,判断这个节点是否遍历到过。深度优先遍历中遍历当前节点的邻节点时,若取到节点了,要先将当前节点压栈,以达到再次回到这个节点的目的。
    // 宽度优先遍历
    function graphBFS(node) {
        const queue = [node]
        const nodeSet = new Set()
        while (queue.length) {
            const curNode = queue.shift()
            nodeSet.add(curNode)
            curNode.nextNodes.forEach(item => {
                if (!nodeSet.has(item)) queue.push(item)
            })
        }
        return [...nodeSet]
    }
    
    // 深度优先遍历
    function graphDFS(node) {
        const stack = [node]
        const hashSet = new Set()
        hashSet.add(node)
        const resArr = []
        while (stack.length) {
            const curNode = stack.pop()
            for (let i of curNode.nextNodes) {
                const item = curNode.nextNodes[i]
                // 记录没遇到过的节点,并且把当前节点先压栈,再把这个邻节点压栈,跳出循环
                if (!hashSet.has(item)) {
                    hashSet.add(item)
                    stack.push(curNode)
                    stack.push(item)
                    break
                }
            }
            if (!resArr.includes(curNode)) resArr.push(curNode)
        }
    }
  1. 找到入度为0的节点,把这个节点的邻节点入度--。循环这个过程
interface Node {
    // 入度
    inNum: number
}
function topologicalSort(graph: { nodes: Node[] }): Node[] {
    const res = []
    const zeroInQueue = []
    // 先把所有入度为0的节点放入
    graph.nodes.forEach((item) => {
        if(!item.inNum) zeroInQueue.push(item)
    })
    while (zeroInQueue.length) {
        // 取出一个入度为0的节点
        const curNode = zeroInQueue.shift()
        // 这个节点的所有邻节点的入度减一
        curNode.nexts.forEach((item) => {
            item.inNum--
            if (!item.inNum) zeroInQueue.push(item)
        })
    }
    return res
}