js数据结构-二叉搜索树

64 阅读1分钟
const COMPARE = {
  LESS_THEN: -1,
  BIGGER_THEN: 1
};

function defaultCompare(a, b) {
  if (a === b) return 0;
  return a < b ? COMPARE.LESS_THEN : COMPARE.BIGGER_THEN;
}

class Node {
  constructor(key) {
    this.key = key;
    this.left = null;
    this.right = null;
  }
}

class BinarySearchTree {
  constructor(compareFn = defaultCompare) {
    this.compareFn = compareFn;
    this.root = null;
  }
  insert(key) {
    if (!this.root) {
      this.root = new Node(key);
    } else {
      this.insertNode(this.root, key);
    }
  }
  insertNode(node, key) {
    if (this.compareFn(key, node.key) === COMPARE.LESS_THEN) {
      if (!node.left) {
        node.left = new Node(key);
      } else {
        this.insertNode(node.left, key);
      }
    } else {
      if (!node.right) {
        node.right = new Node(key);
      } else {
        this.insertNode(node.right, key);
      }
    }
  }
  // 中序遍历
  inOrderTraverse(callback) {
    this.inOrderTraverseNode(this.root, callback);
  }
  inOrderTraverseNode(node, callbackFn) {
    if (node) {
      this.inOrderTraverseNode(node.left, callbackFn);
      callbackFn(node.key);
      this.inOrderTraverseNode(node.right, callbackFn);
    }
  }
  // 返回最小值
  min() {
    return this.minNode(this.root);
  }
  minNode(node) {
    let current = node;
    while (current && current.left) {
      current = current.left;
    }
    return current;
  }
  // 返回最大值
  max() {
    return this.maxNode(this.root);
  }
  maxNode(node) {
    let current = node;
    while (current && current.right) {
      current = current.right;
    }
    return current;
  }
  find(key) {
    return this.findNode(this.root, key);
  }
  findNode(node, key) {
    if (!node) return false;
    if (this.compareFn(key, node.key) === COMPARE.LESS_THEN) {
      return this.findNode(node.left, key);
    } else if (this.compareFn(key, node.key) === COMPARE.BIGGER_THEN) {
      return this.findNode(node.right, key);
    } else {
      return true;
    }
  }
  remove(key) {
    return this.removeNode(this.root, key);
  }
  removeNode(node, key) {
    if (!node) return null;
    if (this.compareFn(key, node.key) === COMPARE.LESS_THEN) {
      node.left = this.removeNode(node.left, key);
      return node;
    } else if (this.compareFn(key, node.key) === COMPARE.BIGGER_THEN) {
      node.right = this.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;
      }
      const aux = this.minNode(node.right);
      node.key = aux.key;
      node.right = this.removeNode(node.right, aux.key);
      return node;
    }
  }
}