lulusir / my-blog

my-blog
https://github.com/lulusir/my-blog/issues
13 stars 1 forks source link

数据结构--笔记--树 #9

Open lulusir opened 6 years ago

lulusir commented 6 years ago

typescript实现版本

一个树结构包含一系列存在父子关系的节点,每个节点都有一个父节点(除了根节点)以及零个或多个子节点。子树为互补相交的有限集合,除了根节点外,每个节点有且只有一个父节点

树是一种分层次组织的结构

树的一些基本术语

image 这样一般的树结构都可以用二叉树来表示。

二叉树和二叉搜索树

二叉树的子节点最多只有两个,一个左节点一个右节点。
二叉树的几个重要性质 image 二叉搜索树(BST)是二叉树的一种,但它只允许左节点储存比父节点小的值,右节点储存比父节点大的值

常用的遍历方法:

  1. preOrderTreverse 先序---根,左子树,右子树
  2. inOrderTraverse 中序---左子树,根,右子树
  3. postOrderTraverse 后序---左子树,右子树,根
  4. levelOrderTraverse 层次便利---从上到下,从左到右

Todo用栈或者队列连实现遍历

class Node {
  constructor (key) {
    this.key = key
    this.left = null
    this.right = null
  }
}
class BinarySearchTree {
  constructor () {
    this.root = null
  }
  insert (key) {
    const newNode = new Node(key)
    if (this.root === null) {
      this.root = newNode
    } else {
      this._insertNode(this.root, newNode)
    }
    console.log(JSON.stringify(this.root, null, 2))
  }
  _insertNode (node, newNode) {
    if (newNode.key < node.key) {
      if (node.left === null) {
        node.left = newNode
      } else {
        this._insertNode(node.left, newNode)
      }
    } else {
      if (node.right === null) {
        node.right = newNode
      } else {
        this._insertNode(node.right, newNode)
      }
    }
  }
  search (key) {
    this._searchNode(this.root, key)
  }
  _searchNode (node, key) {
    if (node === null) {
      return false
    }

    if (key < node.key) {
      return this._searchNode(node.left, key)
    } else if (key > node.key) {
      return this._searchNode(node.right, key)
    } else {
      return true
    }
  }
  /**
   * 中序遍历;从小到大的顺序遍历节点
   * @param {any} cb 
   * @memberof BinarySearchTree
   */
  inOrderTraverse (cb) {
    this._inOrderTraverseNode(this.root, cb)
  }
  _inOrderTraverseNode (node ,cb) {
    if (node !== null) {
      this._inOrderTraverseNode(node.left, cb)
      cb(node.key)
      this._inOrderTraverseNode(node.right, cb)
    }
  }
  /**
   * 先访问根节点,在访问左节点,最后右节点
   * @param {any} cb 
   * @memberof BinarySearchTree
   */
  preOrderTraverse (cb) {
    this._preOrderTraverseNode(this.root, cb)
  }
  _preOrderTraverseNode(node, cb) {
    if (node !== null) {
      cb(node.key)
      this._preOrderTraverseNode(node.left, cb)
      this._preOrderTraverseNode(node.right, cb)
    }
  }
  postOrderTraverse (cb) {
    this._postOrderTraverseNode(this.root, cb)
  }
  _postOrderTraverseNode (node, cb) {
    if (node !== null) {
      this._postOrderTraverseNode(node.left, cb)
      this._postOrderTraverseNode(node.right, cb)
      cb(node.key)
    }
  }
  min () {
    return this._minNode(this.root)
  }
  _minNode (node) {
    if (node) {
      while (node && node.left !== null) {
        node = node.left
      }
      return node.key
    }
    return null
  }
  max () {
    return this._maxNode(this.root)
  }
  _maxNode (node) {
    if (node) {
      while (node && node.right !== null) {
        node = node.right
      }
      return node.key
    }
    return null
  }
  remove (key) {
    this.root = this._removeNode(this.root, key)
  }
  _removeNode (node, key) {
    if (node === null) {
      return null
    }
    if (key < node.key) {
      node.left = this._removeNode(node.left, key)
      return node
    } else if (key > node.key) {
      node.right = this._removeNode(node.right, key)
      return node
    } else {
      // 一个叶节点
      if (node.left === null && node.right === null) {
        node = null
        return node
      } else if (node.left === null) {
        // 存在右侧子节点,直接当前节点的指针指向子节点,跳过当前节点来移除当前节点
        node = node.right
        return  node
      } else if (node.right === null) {
        // 同上
        node = node.left
        return node
      } else {
        var aux = this.findMinNode(node.right) // 找到右侧最小的节点
        node.key = aux.key // 把要删除的节点的值替换成右侧最小节点的值
        node.right = this._removeNode(node.right, aux.key) // 删除掉右侧的这个节点
        return node
      }
    }
  }
  findMinNode (node) {
    return this._findMinNode(node)
  }
  _findMinNode (node) {
    if (node === null) {
      return null
    }
    while (node && node.left !== null) {
      node = node.left
    }
    return node
  }
}
const tree = new BinarySearchTree()
tree.insert(11)
tree.insert(7)
tree.insert(15)
tree.insert(5)
tree.insert(3)
tree.insert(8)
tree.insert(9)
tree.insert(10)
tree.insert(12)
tree.insert(13)
tree.insert(14)
tree.insert(20)
tree.insert(18)
tree.insert(25)
tree.inOrderTraverse(console.log) // 3 5 7 11 15
tree.remove(15)
tree.inOrderTraverse(console.log)
tree.preOrderTraverse(console.log) // 11 7 5 3 15
tree.postOrderTraverse(console.log) // 11 7 5 3 15

平衡二叉树

平衡因子:BF(T) = hL - hR
其中hL,hR分别为左右子树的高度
平衡二叉树(AVL树)
空树,或者任一节点左右子树高度差绝对值不超过1,即|BF(T)| <= 1