来一起刷简单算法题[十二] 树

90 阅读1分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第19天,点击查看活动详情

二叉树

二叉树中的节点最多有两个子节点:一个是左侧子节点,另一个是右侧子节点。

二叉搜索树

二叉搜索树(BST)是二叉树的一种,但是允许你在左侧节点存储(比父节点)小的值,在右侧节点存储(比父节点)大的值。

下面我们来写一个二叉搜索树

export enum Compare {
  LESS_THAN = -1,
  BIGGER_THAN = 1,
  EQUALS = 0
}

export function defaultCompare<T>(a: T, b: T): number {
  if (a === b)
    return Compare.EQUALS

  return a < b ? Compare.LESS_THAN : Compare.BIGGER_THAN
}

import { Compare, defaultCompare } from './utils'

export class Node {
  key: any
  left: null | Node
  right: null | Node
  constructor(key: any) {
    this.key = key // 节点值
    this.left = null // 左侧子节点引用
    this.right = null // 右侧子节点引用
  }
}

/**
 * insert(key):向树中插入一个新的键
 * search(key): 向树中查找一个键,如果节点存在,则返回true;如果不存在,则返回false
 * inOrderTraverse():中序遍历 (左根右)
 * preOrderTraverse(): 前序遍历 (根左右)
 * postOrderTraverse():后序遍历 (左右根)
 * min():返回树中的最小值
 * max():返回树中最大的值
 * remove(key):从树中移除某个键
 */
export class BinarySearchTree {
  compareFn: Function // 比较函数
  root: null | Node
  constructor(compareFn = defaultCompare) {
    this.compareFn = compareFn // 用来比较节点值
    this.root = null // Node类型的根节点
  }

  insert(key: any) {
    if (!this.root) {
      this.root = new Node(key)
      return
    }
    this.insertNode(this.root, key)
  }

  private insertNode(node: Node, key: any) {
    if (this.compareFn(key, node.key) === Compare.LESS_THAN) {
      if (node.left === null)
        node.left = new Node(key)
      else
        this.insertNode(node.left, key)

      return
    }
    if (node.right === null)
      node.right = new Node(key)
    else
      this.insertNode(node.right, key)
  }
   
  // 中序遍历
  inOrderTreeTraverse(callback: Function) {
    this.inOrderTreeTraverseNode(this.root, callback)
  }

  private inOrderTreeTraverseNode(node: Node | null, callback: Function) {
    if (node === null) return
    this.inOrderTreeTraverseNode(node.left, callback)
    callback(node.key)
    this.inOrderTreeTraverseNode(node.right, callback)
  }
  
  // 前序遍历

  preOrderTreeTraverse(callback: Function) {
    this.preOrderTreeTraverseNode(this.root, callback)
  }

  private preOrderTreeTraverseNode(node: Node | null, callback: Function) {
    if (node === null) return
    callback(node.key)
    this.preOrderTreeTraverseNode(node.left, callback)
    this.preOrderTreeTraverseNode(node.right, callback)
  }
    
  // 后续遍历
  postOrderTreeTraverse(callback: Function) {
    this.postOrderTreeTraverseNode(this.root, callback)
  }

  private postOrderTreeTraverseNode(node: Node | null, callback: Function) {
    if (node === null) return
    this.postOrderTreeTraverseNode(node.left, callback)
    this.postOrderTreeTraverseNode(node.right, callback)
    callback(node.key)
  }
}

const tree = new BinarySearchTree()
tree.insert(11)
tree.insert(7)
tree.insert(15)
tree.insert(5)
tree.insert(3)
tree.insert(9)
tree.insert(8)
tree.insert(10)
tree.insert(13)
tree.insert(12)
tree.insert(14)
tree.insert(20)
tree.insert(18)
tree.insert(25)

tree.insert(6)

tree.postOrderTreeTraverse((val: any) => console.log(val))