图
问:
- 图的广度优先遍历和深度优先遍历
- 拓扑排序
解:
- 广度遍历用哈希表存值,判断这个节点是否遍历到过。深度优先遍历中遍历当前节点的邻节点时,若取到节点了,要先将当前节点压栈,以达到再次回到这个节点的目的。
// 宽度优先遍历
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)
}
}
- 找到入度为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
}