定义节点:
a
/ \
c b
/ \ / \
f g d e
function Node(value) {
this.value = value;
this.left = null;
this.right = null;
}
const a = new Node('a')
const b = new Node('b')
const c = new Node('c')
const d = new Node('d')
const e = new Node('e')
const f = new Node('f')
const g = new Node('g')
const h = new Node('h')
a.left = c;
a.right = b;
c.left = f;
c.right = g;
b.left = d;
b.right = e;
深搜
递归
function deepSearch(root, targetNode) {
if (root === null) return false;
if (root.value === targetNode.value) return true;
const left = deepSearch(root.left, targetNode)
const right = deepSearch(root.right, targetNode)
return left || right;
}
迭代
深度优先搜索, 就是 前序遍历
利用栈结构, 先入后出
- 如果弹出的节点有右子树, 先将右子树入栈;
- 如果左子树有值, 再入栈 左子树;
- 再次循环时, 先弹出的永远是 左子树
function dfs(root, targetNode) {
const hasSearch = [root]
let pop = null
while (hasSearch.length !== 0) {
pop = hasSearch.pop()
if (pop.value === targetNode.value) return true
pop.right && hasSearch.push(pop.right)
pop.left && hasSearch.push(pop.left)
}
return false
}
广搜
递归
function wideSearch(rootList, targetNode) {
if (rootList.length === 0) return false
let childList = []
for (const node of rootList) {
if (node === null) continue
if (node.value === targetNode.value) return true
childList.push(node.left, node.right)
}
return wideSearch(childList, targetNode)
}
迭代
利用队列, 先入先出
- 永远先弹出左子节点
- 然后将左子树的子节点们加入队列
- 下一次弹出右子节点
function bfc(root,targetNode) {
const hasSearch = [root]
let pop = null
while (hasSearch.length !== 0) {
pop = hasSearch.pop()
if(pop.value === targetNode.value) return true
pop.left && hasSearch.unshift(pop.left)
pop.right && hasSearch.unshift(pop.right)
}
return false
}
小结
深搜 和 广搜 的迭代方式,只差了两行代码 !!!
- 深搜用了 栈
- 广搜用了 队列