二叉搜索树实现

112 阅读1分钟

二叉搜索树定义

  1. 左子树节点小于根节点
  2. 根节点小于右子树节点

实现功能

  1. 搜索树构建
  2. 搜索树查询
  3. 搜素可迭代遍历
  4. 搜索树删除节点 等功能

代码实现如下

class TreeNode {
  val: number;
  left: TreeNode | null;
  right: TreeNode | null;
  constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) {
    this.val = val === undefined ? 0 : val;
    this.left = left === undefined ? null : left;
    this.right = right === undefined ? null : right;
  }
}

class SearchBST {
  root = null;

  //构造二叉搜索树
  constructor(array: number[] | TreeNode | number) {
    if (Array.isArray(array))
      array.forEach((item) => (this.root = this.insert(this.root, item)));
    else if (typeof array === "number") {
      this.root = new TreeNode(array);
    } else {
      this.root = array;
    }
  }

  //插入二叉搜索树
  insert(root, val) {
    if (!root) {
      return new TreeNode(val);
    } else {
      if (val <= root.val) {
        root.left = this.insert(root.left, val);
      } else {
        root.right = this.insert(root.right, val);
      }
      return root;
    }
  }

  //搜索二叉搜索树
  searchBst(root: TreeNode | null = this.root, val: number): TreeNode | null {
    if (root === null) {
      return root;
    }
    if (root.val > val) {
      return this.searchBst(root.left, val);
    } else if (root.val === val) {
      return root;
    } else {
      return this.searchBst(root.right, val);
    }
  }

  search(val) {
    return this.searchBst(this.root, val);
  }

  //删除二叉搜索树
  remove(val) {
    if (!this.root) {
      this.root = null;
      return null;
    }
    if (this.root.val === val) {
      const maxNode = this.max(this.root.left);
      if (!maxNode) {
        this.root = this.root.right;
        return this.root;
      }
      this.remove(maxNode?.val);
      maxNode.left = this.root.left;
      maxNode.right = this.root.right;
      this.root = maxNode;
      return maxNode;
    } else {
      const p = this._findParent(this.root, val); //父节点
      if (!p) return null;
      const type = p.left?.val === val ? "left" : "right";
      const n = p[type]; //查找到的节点
      //叶子节点直接删除
      if (!n.left && !n.right) {
        p[type] = null;
      } else if (!n.left || !n.right) {
        p[type] = !n.left ? n.right : n.left;
      } else {
        const maxNode = this.max(n.left);
        this.remove(maxNode.val);
        maxNode.left = n.left;
        maxNode.right = n.right;
        p[type] = maxNode;
      }
      return n;
    }
  }

  //查找最大节点
  max(root = this.root) {
    if (!root || !root.right) {
      return root;
    }
    return this.max(root.right);
  }

  //查找最小值
  min(root = this.root) {
    if (!root || !root.left) {
      return root;
    }
    return this.min(root.left);
  }

  //中序遍历-升序
  ascOrder(root = this.root, res = []) {
    if (root) {
      this.ascOrder(root.left, res);
      res.push(root.val);
      this.ascOrder(root.right, res);
    }
    return res;
  }

  //中序遍历-降序
  desOrder(root = this.root, res = []) {
    if (root) {
      this.desOrder(root.right, res);
      res.push(root.val);
      this.desOrder(root.left, res);
    }
    return res;
  }

  //查找节点-返回父节点
  _findParent(root, val) {
    if (!root || (!root.left && !root.right)) {
      return null;
    }
    if (root.left?.val === val || root.right?.val === val) {
      return root;
    } else if (root.val > val) {
      return this._findParent(root.left, val);
    } else {
      return this._findParent(root.right, val);
    }
  }

  *valIterator(root: TreeNode = this.root): Generator<any, any, number> {
    if (root) {
      yield* this.valIterator(root.left);
      yield root.val;
      yield* this.valIterator(root.right);
    }
  }

  [Symbol.iterator] = () => this.valIterator();
}

const root = new SearchBST([1, 2, 6, 7, 0, 23, 8]);

for (const iterator of root) {
  console.log(iterator);
}

使用二叉搜索树查找某个节点的前驱节点【leetcode-面试题 04.06. 后继者】

运行效率

test.png

代码如下

var inorderSuccessor = function (root, p) {
  if (!root) return;
  if (p.val === root.val) {
    return getMin(root.right);
  } else if (p.val < root.val) {
    const temp = inorderSuccessor(root.left, p);
    if (temp === null) {
      return root;
    }
    if (temp) return temp;
  } else {
    return inorderSuccessor(root.right, p);
  }
};

function getMin(root) {
  if (!root || !root.left) return root;
  return getMin(root.left);
}