53 阅读2分钟

什么是树?

一种分层数据的抽象模型

DOM,级联选择器,树形控件。。。

深度优先遍历(dfs)

尽可能深的搜索树的分支 访问根节点,对根节点的children进行挨个(从左遍历到底,在遍历右)深度优先遍历

const tree = {
  val: "a",
  children: [
    {
      val: "b",
      children: [
        {
          val: "d",
          children: [],
        },
        {
          val: "e",
          children: [],
        },
      ],
    },
    {
      val: "c",
      children: [
        {
          val: "f",
          children: [],
        },
        {
          val: "g",
          children: [],
        },
      ],
    },
  ],
};

const dfs = (tree) => {
    console.log(tree.val);
    if(tree.children.length > 0){
        tree.children.forEach(dfs)
    }
}
dfs(tree)

广度优先遍历(bfs)

每个层级都遍历完在遍历下一层

const tree = {
    val: "a",
    children: [
      {
        val: "b",
        children: [
          {
            val: "d",
            children: [],
          },
          {
            val: "e",
            children: [],
          },
        ],
      },
      {
        val: "c",
        children: [
          {
            val: "f",
            children: [],
          },
          {
            val: "g",
            children: [],
          },
        ],
      },
    ],
  };
  
  
  /*
  先访问离根节点最近的节点
新建一个队列,根节点入队
队头出队
队头的children挨个入队
重复2、3,直到队空
  */
  
  const bfs = (tree) => {
   const q = [tree]
   while(q.length > 0){
    const n = q.shift()
    console.log(n.val);
    n.children.forEach(child => {
        q.push(child)
    })
   }
  }
  bfs(tree)

const bt = {
  val: 1,
  left: {
    val: 2,
    left: {
      val: 4,
      left: null,
      right: null,
    },
    right: {
      val: 5,
      left: null,
      right: null,
    },
  },
  right: {
    val: 3,
    left: {
      val: 6,
      left: null,
      right: null,
    },
    right: {
      val: 7,
      left: null,
      right: null,
    },
  },
};

先序遍历(preorder)

访问根节点 对根节点的左子树进行先序遍历 对根节点的右子树进行先序遍历

const p = (tree) => {
    if(tree){
        console.log(tree.val);
        p(tree.left)
        p(tree.right)
    }
}
//非递归版
const p1 = (tree) => {
    if(tree){
      const stack = [tree]
  while(stack.length){
    const n = stack.pop()
    console.log(n.val);
    //因为后进先出,所以右先进去
    if(n.right) stack.push(n.right)
    if(n.left) stack.push(n.left)
  }
    }
}

中序遍历(inorder)

对根节点的左子树进行中序遍历 访问根节点 对根节点的右子树进行中序遍历

const i = (tree) => {
  if (tree) {
    i(tree.left);
    console.log(tree.val);
    i(tree.right);
  }
};
//先进根节点,在进左节点,出去左节点,在出根节点,最后在进右节点然后出
const i1 = (tree) => {
  if (tree) {
    const stack = [];
    let p = tree;
    while (stack.length || p) {
      while (p) {
        stack.push(p);
        p = p.left;
      }
      const n = stack.pop();
      console.log(n.val);
      p = n.right;
    }
  }
};

后序遍历(postorder)

对根节点的左子树进行中后序遍历 对根节点的右子树进行后续遍历 访问根节点

const p = (tree) => {
if(tree){
    p(tree.left)
    p(tree.right)
    console.log(tree.val);
}
}

//先序遍历,然后反过来输出,
const p1 = (tree) => {
    if(tree){
      const stack1 = []
      const stack = [tree]
  while(stack.length){
    const n = stack.pop()
    stack1.push(n)
    if(n.left) stack.push(n.left)
    if(n.right) stack.push(n.right)
  }

  while(stack1.length){
    const n = stack1.pop()
    console.log(n.val);
  }
    }
}

最大深度

   var maxDepth = function(root) {
  //s深度优先的过程中记录最大层级
  let res = 0
  const dfs = (n,l) => {
      if(n){
          if(!n.left && !n.right){
              res = Math.max(res,l)
          }
          dfs(n.left,l + 1)
          dfs(n.right,l + 1)
      }

  }
  dfs(root,1)
  return res};

最小深度

 var minDepth = function(root) {
    const bfs = (n) => {
        if(n){
            const q = [[root,1]]
            while(q.length){
                const [a,l] = q.shift()
                if(!a.left&&!a.right){
                    return l
                }
                if(a.left) q.push([a.left,l+1])
                if(a.right) q.push([a.right,l+1])
            }
        }
        return 0
    }
    return bfs(root)
};