[TOC]
前端工作中常见的树包括:DOM树、级联选择、树形控件...
JS中没有树结构数据,但可以用Object和Array来构建树。
{
value:"a",
label:"",
children:[
{
value:"b",
label:"",
children:[
{
value:"d",
label:"",
children:[],
}
],
},
{
value:"c",
label:"",
children:[
{
value:"e",
label:"",
children:[],
},
{
value:"f",
label:"",
children:[],
}
],
},
]
}
a
/ \
b c
| / \
d e f
树常见的操作
- 深度/广度优先遍历
- 先中后序遍历
深度优先遍历算法
- 先访问根节点
- 对根节点的children挨个进行深度优先遍历
上图执行的顺序是:a-b-d-c-e-f
// 参数root就是上面定义的数结构
const dfs = (root) =>{
console.log(root.value)
root.children.forEach(child=>dfs(child))
}
广度优先遍历算法
- 新建一个队列,把根节点入队
- 把队头出队并访问
- 把队头的children挨个入队
- 重复2、3直至队列为空
const bfs = (root) =>{
const q = [root]
while(q.length>0){
const n =q.shift()
console.log(n.value)
n.children.forEach(child=>q.push(child))
}
}
上图执行的顺序是:a-b-c-d-e-f
什么是二叉树
- 树中每个节点最多只能有两个子节点
- 在JS中通常用Object来模拟二叉树
const tree = {
value:'a',
left:{
value:'b',
left:{
value:'d',
left:null,
right:null,
},
right:{
value:'e',
left:null,
right:null,
},
},
right:{
value:'c',
left:{
value:'f',
left:null,
right:null,
},
right:{
value:'g',
left:null,
right:null,
},
},
}
先序遍历算法(根-左-右)
- 访问根节点
- 对根节点的左子树进行先序遍历
- 对根节点的右子树进行先序遍历
// 递归版
const preorder=(root)=>{
if(!root) return
console.log(root.value)
preorder(root.left)
preorder(root.right)
}
// 非递归版
const preorder=(root)=>{
if(!root) return
const stack = [root]
while(stack.length){
const n = stack.pop()
console.log(n.value)
// 栈是后进先出结构,要先访问left要最后入栈
if(n.right) stack.push(n.right)
if(n.left) stack.push(n.left)
}
}
中序遍历算法(左-根-右)
- 对根节点的左子树进行中序遍历
- 访问根节点
- 对根节点的右子树进行中序遍历
// 递归版
const inorder=(root)=>{
if(!root) return
inorder(root.left)
console.log(root.value)
inorder(root.right)
}
// 非递归版
const inorder=(root)=>{
if(!root) return
const stack = []
let p = root
while(stack.length || p){
while(p){
stack.push(p)
p = p.left
}
const n = stack.pop()
console.log(n.value)
p = n.right
}
}
后序遍历算法(左-右-根)
- 对根节点的左子树进行后序遍历
- 对根节点的右子树进行后序遍历
- 访问根节点
// 递归版
const postorder=(root)=>{
if(!root) return
postorder(root.left)
postorder(root.right)
console.log(root.value)
}
// 非递归版 - 利用先序的规则进行倒序输出
const postorder=(root)=>{
if(!root) return
const stack = [root]
const outStack = []
while(stack.length){
const n = stack.pop()
outStack.push(n)
if(n.left) stack.push(n.left)
if(n.right) stack.push(n.right)
}
outStack.forEach(item=>console.log(item.value))
}
leetcode练习题解
深度优先
https://leetcode-cn.com/problems/maximum-depth-of-binary-tree/
https://leetcode-cn.com/problems/path-sum/
广度优先
https://leetcode-cn.com/problems/minimum-depth-of-binary-tree/
层序遍历=广度
https://leetcode-cn.com/problems/binary-tree-level-order-traversal/
中序遍历
https://leetcode-cn.com/problems/binary-tree-inorder-traversal/