Предположим, у вас есть традиционные bfs
и dfs
dfs(G, node, visited):
if node in visited:
return
visited.mark(child)
for children in node:
dfs(G, child, visited)
bfs(G, queue, visited):
node = queue.dequeue()
if node in visited:
return bfs(G, queue, visited)
visited.mark(node)
for children in node not in visited:
queue.enqueue(child)
# explore next node
bfs(G, queue, visited)
Мы можем просто изменить их оба.
- dfs имеет логический флаг
onleaf
, которыйв основном прервать исследование - bfs имеет хук:
dfs
(сам!), который вызывается перед исследованием bfs следующего узла
#dfs stops exploration if he found a leaf
dfs(G, node, visited):
if node in visited:
return
visited.mark(child)
+ if node has no children
+ onleaf = true
+ return onleaf
for children in node:
+ hasleaf = dfs(G, child, visited)
+ if hasleaf:
+ return true
bfs(G, queue, visited):
node = queue.dequeue()
if node in visited:
return bfs(G, queue, visited)
visited.mark(node)
for children in node not in visited:
queue.enqueue(child)
+ # explore next node
+ # current node has setted the next candidates, just dfs it
+ dfs(G, node, visited)
+ #process to explore the queue as usual
+ bfs(G, queue, visited)
ниже js
/* useless just to get some data and debugging info */
const makeTree = (d => {
let id = 0
const rec = (depth = 4) => {
if (depth == 0) return {id: id++, children:[]}
return node = {
id: id++,
children: Array(1 + Math.floor(Math.random()*5))
.fill(0)
.map(rec.bind(null, depth-1))
}
}
return _ => ({ tree: rec(), id })
})()
const proxy = s => {
const old = s.add
s.add = function(node){
console.log('visit ', node.id)
return old.apply(this, arguments)
}
return s
}
/* ---------------end of useless ---------------------*/
let visited = proxy(new Set())
const dfs = node => {
if (visited.has(node)) { return }
visited.add(node)
if (!node.children.length) { return true }
return node.children.some(dfs)
}
const bfs = (queue) => {
if(!queue.length) { return }
const node = queue.shift()
if (visited.has(node)) { return bfs(queue) }
visited.add(node)
queue.push(...node.children)
dfs(node)
bfs(queue)
}
const {tree, id} = makeTree()
bfs([tree])
console.log('explored', visited.size, 'expect', id)