数据结构——二叉树

193 阅读2分钟

PK创意闹新春,我正在参加「春节创意投稿大赛」,详情请看:春节创意投稿大赛

二叉树 是基于的数据结构, 它的每个节点至多含有2个子节点:左子节点 和 右子节点;

graph TB
root((根节点)) --> leftNode1((左子树))
root((根节点)) --> rightNode1((右子树))
leftNode1((左子树)) --> leftNode2((叶子结点))
leftNode1((左子树)) --> rightNode2((叶子结点))
rightNode1((右子树)) --> leftNode3((叶子结点))
rightNode1((右子树)) --> leftNode4((叶子结点))

基本的结构代码:

class TreeNode {
  public value: number;
  public left: TreeNode | null;
  public right: TreeNode | null;
  constructor(value?: number, left?: TreeNode | null, right?: TreeNode | null) {
    this.value = value === undefined ? 0 : value;
    this.left = left === undefined ?  null : left
    this.right = right === undefined ?  null : right
  }
}

示例: 一个 二叉树 [7, 4, 5, 1, 3, 6, 8]

graph TB
root((7)) --> leftNode1((4))
root((7)) --> rightNode1((5))
leftNode1((4)) --> leftNode2((1))
leftNode1((4)) --> rightNode2((3))
rightNode1((5)) --> leftNode3((6))
rightNode1((5)) --> leftNode4((8))
const nums: number[] = [7, 4, 5, 1, 3, 6, 8]
const root: TreeNode =  new TreeNode(7)
const n: number = nums.length
function createTree (root: TreeNode, index: number) {
  const leftIndex: number = 2 * index + 1
  const rightIndex: number = leftIndex + 1
  if (leftIndex < n) {
    root.left = new TreeNode(nums[leftIndex])
    createTree(root.left, leftIndex)
  }
  if (rightIndex < n) {
    root.right = new TreeNode(nums[rightIndex])
    createTree(root.right, rightIndex)
  }
}
createTree(root, 0)

image.png

前序遍历

遍历顺序: 先访问 根节点 然后再遍历左子树,最后遍历右子树 比如示例的二叉树,前序遍历:[7,4,1,3,5,6,8]

function preorderTraversal (root: TreeNode | null): number[] {
  if (!root) return []
  const left: number[] = preorderTraversal(root.left)
  const right: number[] = preorderTraversal(root.right)
  return [root.value, ...left, ...right]
}
const res: number[] = preorderTraversal(root) // [7, 4, 1, 3, 5, 6, 8]

image.png

中序遍历

遍历顺序: 先访问 左子树 然后再遍历根节点,最后遍历右子树 比如示例的二叉树,中序遍历:[1,4,3,7,6,5,8]

function inorderTraversal(root: TreeNode | null): number[] {
  if (!root) return []
  const left: number[] = inorderTraversal(root.left)
  const right: number[] = inorderTraversal(root.right)
  return [...left, root.value, ...right]
}
const inRes: number[] = inorderTraversal(root) // [1, 4, 3, 7, 6, 5, 8]

image.png

后序遍历

遍历顺序: 先访问 左子树 然后再遍历右子树,最后遍历根节点 比如示例的二叉树,后序遍历:[1,3,4,6,8,5,7]

function postorderTraversal(root: TreeNode | null): number[] {
  if (!root) return []
  const left: number[] = postorderTraversal(root.left)
  const right: number[] = postorderTraversal(root.right)
  return [...left, ...right, root.value]
}
console.log(postorderTraversal(root)) // [1, 3, 4, 6, 8, 5, 7 ]

image.png

前序 / 后序 + 中序 会确定一个二叉树

  1. 后序 最后一个元素 为根元素
  2. 前序 第一个元素 为 根元素

前序 + 中序

// 前序 [7, 4, 1, 3, 5, 6, 8], 中序 [1, 4, 3, 7, 6, 5, 8]
function createBinaryTree (preorder: number[], inorder: number[]): TreeNode | null {
  // 先遍历中序的索引
  const in_map: Map<number, number> = new Map()
  inorder.forEach((value, index) => {
    in_map.set(value, index)
  })
  let pre_index: number = 0
  function dsf (left: number, right: number): TreeNode | null {
    console.log(left, right)
    if (left > right) return null
    const val: number = preorder[pre_index]
    pre_index++
    const node: TreeNode = new TreeNode(val)
    const index: number = in_map.get(val) as number
    node.left = dsf(left, index - 1)
    node.right = dsf(index + 1, right)
    return node
  }
  return dsf(0, preorder.length - 1)
}
console.log(createBinaryTree([7, 4, 1, 3, 5, 6, 8], [1, 4, 3, 7, 6, 5, 8]))

后序 + 中序

// 后序 [1, 3, 4, 6, 8, 5, 7 ], 中序 [1, 4, 3, 7, 6, 5, 8]
function createPostBinaryTree (postorder: number[], inorder: number[]): TreeNode | null {
  // 先遍历中序的索引
  const in_map: Map<number, number> = new Map()
  inorder.forEach((value, index) => {
    in_map.set(value, index)
  })
  let post_index: number = postorder.length - 1
  function dsf (left: number, right: number): TreeNode | null {
    if (left > right) return null
    console.log(left, right)
    const val: number = postorder[post_index]
    post_index--
    const node: TreeNode = new TreeNode(val)
    const index: number = in_map.get(val) as number
    node.right = dsf(index + 1, right)
    node.left = dsf(left, index - 1)
    return node
  }
  return dsf(0, postorder.length - 1)
}

console.log(createPostBinaryTree([1, 3, 4, 6, 8, 5, 7 ], [1, 4, 3, 7, 6, 5, 8]))

广度优先遍历

一层一层遍历

function bfs(root: TreeNode | null):number[] {
  if (!root) return []
  const result: number[] = []
  const queue: TreeNode[] = [root]
  while(queue.length) {
    const node: TreeNode = queue.shift() as TreeNode
    result.push(node.value)
    if (node.left) {
      queue.push(node.left)
    }
    if (node.right) {
      queue.push(node.right)
    }
  }
  return result
}
console.log(bfs(root)) // [7, 4, 5, 1, 3, 6, 8]

image.png

深度优先遍历

function dfs (root: TreeNode | null): number[]{
  if (!root) return []
  const result: number[] = []
  const queue: TreeNode[] = [root]
  while(queue.length) {
    const node: TreeNode = queue.pop() as TreeNode
    result.push(node.value)
    if (node.right) {
      queue.push(node.right)
    }
    if (node.left) {
      queue.push(node.left)
    }
  }
  return result
}

console.log(dfs(root)) // [7, 4, 1, 3, 5, 6, 8 ]

image.png