jstructures
Version:
The project is JavaScript Data Structures incudes Vector, List, Tree, Graph, Heap...etc
107 lines (98 loc) • 2.77 kB
JavaScript
const BinNode = require("../bin-tree/bin-node");
const BinTree = require("../bin-tree/bin-tree");
/**
* BST 类(二叉搜索树类, 继承自 BinTree)
* @class
* @return {BST} Instance
*/
class BST extends BinTree {
/**
* 查找元素 e 所在的节点
* @time O(logN), Ω(N)
* @space O(1)
*
* @param {Anyone} e 要搜索的元素
*
* @return {[BinNode]} 返回两项,第一项是搜索命中的节点,第二项是命中节点的父节点
*/
search(e) {
return BST.searchIn(this.root, e, null);
}
/**
* 插入元素
* @time O(logN), Ω(N)
* @space O(1)
* @param {Anyone} e 要插入的数据元素
*
* @return {BinNode}
*/
insert(e) {
const [x, p] = this.search(e);
if (x) return x; // 已存在
if (!p) return this.insertAsRoot(e); // 作为根插入
if (e < p.data) return this.insertAsLC(p, e); // 作为左孩子插入
return this.insertAsRC(p, e); // 作为右孩子插入
}
/**
* 删除元素, 注意是删除节点,非节点为根的子树
* @time O(logN), Ω(N)
* @space O(1)
* @param {Anyone} e 要插入的数据元素
*
* @return {Boolean} 是否成功删除
*/
remove(e) {
const [x, p] = this.search(e);
if (!x) return false; // 不存在
const succ = BST.removeAt(x, p);
this.size -= 1;
this.updateHeightAbove(succ);
return true;
}
/**
* 删除某个节点
* @time O(1)
* @space O(1)
* @param {BinNode} x 要删除的节点
*
* @return {BinNode} 返回接替者
*/
static removeAt(x) {
let succ;
const [parent, key] = x.fromParentTo;
if (!x.hasLChild) {
// 左孩子不存在, 右孩子也可能不存在
parent[key] = x.rc;
succ = x.rc;
} else if (!x.hasRChild) {
// 左孩子存在,右孩子不存在
parent[key] = x.lc;
succ = x.lc;
} else {
// 左右孩子都存在
const w = x.succ;
const u = w.parent;
BinNode.swap(x, w); // 交换当前节点和后继节点的数据
u[u === x ? "rc" : "lc"] = w.rc; // 隔离节点
succ = w.rc;
}
if (succ) succ.parent = parent; // 将删除节点的接替者跟parent连接
return succ;
}
/**
* 以 v 为根节点查找元素 e 所在的节点
* @time O(logN)
* @space O(1)
*
* @param {BinNode} v 要搜索的树的根节点
* @param {Anyone} e 要搜索的元素
* @param {BinNode} p 当前搜索节点的父节点
*
* @return {[BinNode]} 返回两项,第一项是搜索命中的节点,第二项是命中节点的父节点
*/
static searchIn(v, e, parent) {
if (!v || e === v.data) return [v, parent];
return BST.searchIn(e < v.data ? v.lc : v.rc, e, v);
}
}
module.exports = BST;