前言:二叉树是只有一个根节点,每个结点最多有两个子树的树结构。通常子树被称作“左子树”(left subtree)和“右子树”(right subtree)。

二叉树的五种基本形态

  1. 空二叉树(无根节点)
  2. 只有一个根结点
  3. 只有左子树
  4. 只有右子树
  5. 完全二叉树

创建一棵二叉排序树

需要思考:左节点的值全部小于根节点的,右节点反之

  1. 创建一个初始化二叉树的构造函数,使其具有两个属性:根节点,插入方法

    function init(){
      this.root = null;
      this.insert = insert;
      this.show = ()=>{
        console.log(this.root);
      }
    }
    
  2. 创建一个节点生成的构造函数,有三个属性:当前值,左节点及右节点

    function Node(data, left, right){
      this.data = data;
      this.left = left;
      this.right = right;
    }
    
  3. 插入函数的实现,在此需要用到循环对比,如果当前插入值小于根节点,就将其和根节点root的左孩子比较,1.左孩子不存在则直接填入,2.存在则将左孩子假设为根节点root ’ ,继续与根节点root ’ 比较…。实现方法如下:

    function insert(data){
      let newNode = new Node(data, null, null);
      //根不存在,直接设置为根节点
      if(!this.root){
        this.root = newNode;
      }else{
      	//current:循环条件,对比直至找不到左或右子节点,结束循环
        let current = this.root;
        //parent:临时保存现在的根节点root',结束循环前将节点插入root’的左或右
        let parent;
        while(current){
          parent = current;
          if(data < current.data){
            current = current.left;
            if(current === null){
              parent.left = newNode;
              break;
            }
          }else{
            current = current.right;
            if(current === null){
              parent.right = newNode;
              break;
            }
          }
        }
      }
    }
    
  4. 检验是否创建成功

    let binaryTree = new init();
    binaryTree.insert(3);
    binaryTree.insert(2);
    binaryTree.insert(5);
    binaryTree.insert(6);
    binaryTree.insert(3);
    binaryTree.insert(5);
    

创建二叉树如下:
二叉树的js相关操作

遍历二叉树

分为:

  1. 前序遍历
  2. 中序遍历
  3. 后序遍历

注意:

  • 所谓的前中后序遍历指的是根节点,例如:前序就是根在前,按照根左右的顺序;中序即左根右。
  • 不论是哪一种遍历类型,其遍历方式都是一样的,都是从根节点走下去,只是打印顺序不一样

添加read遍历方法:

function init(){
  this.root = null;
  this.insert = insert;
  this.show = ()=>{
    console.log(this.root);
  }
  **this.read = orderMap;**
}

实现read方法:

/**
 * 前、中、后序遍历
 * @param {遍历类型} type
 */
function orderMap(type){
  deepMap(this.root);
  function deepMap(current){
    if(!current){
      return;
    }
    let arr = [
      ()=>console.log(current.data),
      ()=>current.left && deepMap(current.left),
      ()=>current.right && deepMap(current.right)
    ];
    let order = [];
    switch(type){
      case 1: order = [0,1,2];break;
      case 2: order = [1,0,2];break;
      case 3: order = [1,2,0];break;
      default: break;
    }
    order.map(item=>{
      arr[item]();
    })
  }
}

在创建二叉树后,调用read方法,就可以实现了

binaryTree.read(1)    //前序:3 2 5 3 6 5
binaryTree.read(2)    //中序:2 3 3 5 5 6
binaryTree.read(3)    //后序:2 3 5 6 5 3

查找树的最大最小值(最左最右)

即:最左为最小值,最右为最大值,以下为查找最小值

function findMin(current){
  let min;
  while(current){
    min = current.data;
    current = current.left;
  }
  return min;
}
console.log(binaryTree.findMin(binaryTree.root))		//Node 2

删除节点

被删除节点分为三种情况:

  • 为叶子节点(直接删除)
  • 仅有一个子节点(假设只有右节点,令node.right = node.right.right;左同理)
  • 有两个子节点(从待删除节点的左子树找节点值最大的节点A,替换待删除节点,并删除节点A;从待删除节点的右子树找节点值最小的节点A,替换待删除节点,并删除节点A。)

具体实现:
先创建一个新的二叉树:

let binaryTree2 = new init();
binaryTree2.insert(10);
binaryTree2.insert(8);
binaryTree2.insert(7);
binaryTree2.insert(9);
binaryTree2.insert(14);
binaryTree2.insert(11);
binaryTree2.insert(17);
binaryTree2.insert(10);
binaryTree2.insert(12);
binaryTree2.insert(13);
binaryTree2.insert(15);
binaryTree2.insert(19);

在init函数中添加删除方法:

function init(){
  this.root = null;
  this.insert = insert;
  this.show = ()=>{
    console.log(this.root);
  }
  this.read = orderMap;		//前中后遍历
  this.findMin = findMin;		//当前树的最小值节点
  this.deleteNode = deleteNode;		//删除某个节点
}

完成删除函数(有两个子节点的采用第二种,即用右子树最小值替换):

function deleteNode(data){
  let _this = this;
  del(this.root, data)
  function del(node, data){
    if(!node){
      return null;
    }
    if(node.data == data){
      //被删除节点没有子节点
      if(node.left === null && node.right === null) {
        console.log(node)
        return null;
      }
      //只有右节点
      else if(node.left === null ) {
        return node.right;
      } 
      //只有左节点
      else if(node.right === null){
        return node.left;
      }else{
        let minRightNode = _this.findMin(node.right);
        node.data = minRightNode.data;
        node.right = del(node.right, node.data);
        return node;
      }
    }else if(data < node.data){
      node.left = del(node.left, data);
      return node;
    }else{
      node.right = del(node.right, data);
      return node;
    }
  }
}

验证:

binaryTree2.deleteNode(14);
console.log('删除节点14')
binaryTree2.show()

相关文章: