数据结构-树

[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

树常见的操作

  • 深度/广度优先遍历
  • 先中后序遍历
深度优先遍历算法
  1. 先访问根节点
  2. 对根节点的children挨个进行深度优先遍历

上图执行的顺序是:a-b-d-c-e-f

// 参数root就是上面定义的数结构
const dfs = (root) =>{
  console.log(root.value)
  root.children.forEach(child=>dfs(child))
}
广度优先遍历算法
  1. 新建一个队列,把根节点入队
  2. 把队头出队并访问
  3. 把队头的children挨个入队
  4. 重复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,
    },
  },
}
先序遍历算法(根-左-右)
  1. 访问节点
  2. 对根节点的子树进行先序遍历
  3. 对根节点的子树进行先序遍历
// 递归版
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)
  }
}
中序遍历算法(左-根-右)
  1. 对根节点的子树进行中序遍历
  2. 访问节点
  3. 对根节点的子树进行中序遍历
// 递归版
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
  }
}
后序遍历算法(左-右-根)
  1. 对根节点的子树进行后序遍历
  2. 对根节点的子树进行后序遍历
  3. 访问节点
// 递归版
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/

你可能感兴趣的:(数据结构-树)