【JavaScript数据结构】二叉搜索树

55 阅读1分钟

二叉搜索树(BST)是一种二叉树,其中每个节点遵循以下属性:

  • 节点的左子树只包含小于当前节点的值的节点。
  • 节点的右子树只包含大于当前节点的值的节点。
  • 左右子树本身也是二叉搜索树。

以下是一个二叉搜索树的实现及详细注释:

定义二叉搜索树节点:

class TreeNode {
  constructor(value) {
    this.value = value;       // 节点的值
    this.left = null;        // 左子节点
    this.right = null;       // 右子节点
  }
}

二叉搜索树的定义与操作:

class BinarySearchTree {
  constructor() {
    this.root = null; // 树的根节点
  }

  // 插入节点
  insert(value) {
    const newNode = new TreeNode(value);
    if (!this.root) {
      this.root = newNode;
    } else {
      this._insertNode(this.root, newNode);
    }
  }

  _insertNode(node, newNode) {
    if (newNode.value < node.value) {
      if (!node.left) {
        node.left = newNode;
      } else {
        this._insertNode(node.left, newNode);
      }
    } else if (newNode.value > node.value) {
      if (!node.right) {
        node.right = newNode;
      } else {
        this._insertNode(node.right, newNode);
      }
    } // 如果新节点的值等于当前节点值,我们不插入,保持唯一值。
  }

  // 查找节点
  search(value) {
    return this._searchNode(this.root, value);
  }

  _searchNode(node, value) {
    if (!node) return false;

    if (value < node.value) {
      return this._searchNode(node.left, value);
    } else if (value > node.value) {
      return this._searchNode(node.right, value);
    } else {
      return true;  // 找到节点
    }
  }

  // 中序遍历
  inOrder(callback) {
    this._inOrder(this.root, callback);
  }

  _inOrder(node, callback) {
    if (node) {
      this._inOrder(node.left, callback);
      callback(node.value);
      this._inOrder(node.right, callback);
    }
  }

  // 删除节点
  remove(value) {
    this.root = this._removeNode(this.root, value);
  }

  _removeNode(node, value) {
    if (!node) return null;

    if (value < node.value) {
      node.left = this._removeNode(node.left, value);
      return node;
    } else if (value > node.value) {
      node.right = this._removeNode(node.right, value);
      return node;
    } else { // 当前节点就是要删除的节点
      // 无子节点
      if (!node.left && !node.right) {
        return null;
      }
      // 只有一个子节点
      if (!node.left) {
        return node.right;
      } else if (!node.right) {
        return node.left;
      }
      // 有两个子节点
      const aux = this._findMinNode(node.right);
      node.value = aux.value;
      node.right = this._removeNode(node.right, aux.value);
      return node;
    }
  }

  _findMinNode(node) {
    while (node && node.left) {
      node = node.left;
    }
    return node;
  }
}

使用示例:

const bst = new BinarySearchTree();

bst.insert(15);
bst.insert(10);
bst.insert(25);
bst.insert(7);
bst.insert(13);
bst.insert(20);
bst.insert(27);

console.log(bst.search(13));  // true
console.log(bst.search(100)); // false

bst.inOrder(value => console.log(value)); 
// 输出:7, 10, 13, 15, 20, 25, 27

bst.remove(15);
bst.inOrder(value => console.log(value));
// 输出:7, 10, 13, 20, 25, 27