数据结构与算法--二叉搜索树

/**
 * 二叉搜索树(BST):
 *  只允许左侧节点存储小的值,右侧节点存储大(大于或等于)的值
 * @constructor
 */
function BinarySearchTree() {
  function Node(key) {
    this.key = key;
    this.left = null;
    this.right = null;
  }

  let root = null;

  /**
   * 计算树的高度
   * @param node
   */
  this.height = function (node) {
    if (node === null) {
      return -1;
    }

    let leftTreeHeight = this.height(node.left);
    let rightTreeHeight = this.height(node.right);
    return Math.max(leftTreeHeight, rightTreeHeight) + 1;
  };

  /**
   * 平衡二叉树
   * @param node
   * @param element
   */
  this.balanceInsertNode = function (node, element) {
    if (node === null) {
      node = new Node(element);
    } else if (element < node.key) {
      node.left = this.insertNode(node.left, element);

    }
  };


  /**
   * 向树种插入一个新的键
   * @param key
   */
  this.insert = function (key) {
    let newNode = new Node(key);

    if (root === null) {
      // 存在根节点
      root = newNode;
    } else {
      // 添加到子节点树
      this.insertNode(root, newNode);
    }
  };


  this.insertNode = function (root, newNode) {
    if (newNode.key < root.key) {
      // 左子树
      if (root.left === null) {
        root.left = newNode;
      } else {
        this.insertNode(root.left, newNode);
      }
    } else {
      // 右子树
      if (root.right === null) {
        root.right = newNode;
      } else {
        this.insertNode(root.right, newNode);
      }
    }
  };

  /**
   * 中序遍历:左节点 --> 节点键值 --> 右节点
   * @param callback:对遍历的节点所进行的操作
   */
  this.inOrderTraverse = function (callback) {
    if (root !== null) {
      inOrderTraverseNode(root, callback);
    }

    function inOrderTraverseNode(node, callback) {
      inOrderTraverseNode(node.left, callback);
      callback && callback(node.key);
      inOrderTraverseNode(node.right, callback);
    }
  };

  /**
   * 先序遍历:节点键值 --> 左节点 --> 右节点
   * @param callback:对遍历的节点所进行的操作
   */
  this.preOrderTraverse = function (callback) {
    if (root !== null) {
      preOrderTraverseNode(root, callback);
    }

    function preOrderTraverseNode(node, callback) {
      callback && callback(node.key);
      preOrderTraverseNode(node.left, callback);
      preOrderTraverseNode(node.right, callback);
    }
  };

  /**
   * 后序遍历:左节点 --> 右节点 --> 节点键值
   * @param callback: 对遍历的节点所进行的操作
   */
  this.postOrderTraverseNode = function (callback) {
    if (root !== null) {
      postOrderTraverseNode(root, callback);
    }

    function postOrderTraverseNode(node, callback) {
      callback && callback(node.key);
      postOrderTraverseNode(node.right, callback);
      postOrderTraverseNode(node.key, callback);
    }
  };

  /**
   * 树的最小值:即是树最左边的节点值
   */
  this.min = function () {
    return minNode(root);

    function minNode(node) {
      if (node) {
        while (node && node.left) {
          node = node.left;
        }

        return node.key;
      }

      return null;
    }
  };

  this.min1 = function () {
    const node = minNode(root);

    function minNode(node) {
      if (node.left === null) {
        return node;
      }
      return minNode(node.left);
    }
  };

  /**
   * 树的最大值:即是树的最右边的节点值
   */
  this.max = function () {
    return maxNode(root);

    function maxNode(node) {
      if (node) {
        while (node && node.right) {
          node = node.right;
        }
        return node.key;
      }

      return null;
    }
  };

  /**
   * 使用递归:
   *  (1)递归的结束条件
   *  (2)递归的循环指令
   * @returns {*}
   */
  this.max1 = function () {
    const node = maxNode(root);
    return node.key;

    function maxNode(node) {
      if (node.right === null) {
        return node;
      }
      return maxNode(node.right);
    }
  };

  /**
   * 在树种搜索节点值
   * @param key
   */
  this.search = function (key) {
    return searchNode(root, key);

    function searchNode(node, key) {
      if (node === null) {
        return false;
      }

      if (key < node.key) {
        return searchNode(node.left, key);
      } else if (key > node.key) {
        return searchNode(node.right, key);
      } else {
        return true;
      }
    }
  };

  /**
   * 移除一个节点
   * @param key
   */
  this.remove = function (key) {
    root = removeNode(root, key);

    function removeNode(node, key) {
      if (node === null) {
        return null;
      }

      if (key < node.key) {
        node.left = removeNode(node.left, key);
        return node;
      } else if (key > node.key) {
        node.right = removeNode(node.right, key);
        return node;
      } else {
        // 第一种情况----一个叶节点
        if (node.left === null && node.right === null) {
          node = null;
          return node;
        }

        // 第二种情况----一个只有一个子节点的节点
        if (node.left === null) {
          node = node.right;
          return node;
        } else if (node.right === null) {
          node = node.left;
          return node;
        }

        // 第三种情况----一个有两个子节点的节点
        let aux = findMinNode(node.right);
        node.key = aux.key;
        node.right = removeNode(node.right, aux.key);
        return node;
      }

      function findMinNode(node) {
        while (node && node.right) {
          node = node.right;
        }
        return node;
      }
    }
  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值