AVL树
平衡二叉搜索树是一种自平衡的二叉搜索树,其中任何节点的两个子树的高度差最多为1。其中最常见的平衡二叉搜索树是AVL树。
定义AVL树节点:
class AVLTreeNode {
constructor(value) {
this.value = value;
this.left = null;
this.right = null;
this.height = 1; // 默认高度为1
}
}
AVL树的定义及其操作:
class AVLTree {
constructor() {
this.root = null;
}
// 获取节点的高度
_getHeight(node) {
return node ? node.height : 0;
}
// 获取节点的平衡因子
_getBalanceFactor(node) {
return this._getHeight(node.left) - this._getHeight(node.right);
}
// 右旋转
_rotateRight(y) {
const x = y.left;
const T3 = x.right;
x.right = y;
y.left = T3;
y.height = Math.max(this._getHeight(y.left), this._getHeight(y.right)) + 1;
x.height = Math.max(this._getHeight(x.left), this._getHeight(x.right)) + 1;
return x;
}
// 左旋转
_rotateLeft(z) {
const y = z.right;
const T2 = y.left;
y.left = z;
z.right = T2;
z.height = Math.max(this._getHeight(z.left), this._getHeight(z.right)) + 1;
y.height = Math.max(this._getHeight(y.left), this._getHeight(y.right)) + 1;
return y;
}
// 插入节点
insert(value) {
this.root = this._insertNode(this.root, value);
}
_insertNode(node, value) {
if (!node) return new AVLTreeNode(value);
// 正常的BST插入
if (value < node.value) {
node.left = this._insertNode(node.left, value);
} else if (value > node.value) {
node.right = this._insertNode(node.right, value);
} else {
return node;
}
// 更新高度
node.height = 1 + Math.max(this._getHeight(node.left), this._getHeight(node.right));
// 获取平衡因子检查是否失衡
let balance = this._getBalanceFactor(node);
// 进行旋转操作,以保持树的平衡
// Left Heavy
if (balance > 1) {
// Left Right Heavy
if (value > node.left.value) {
node.left = this._rotateLeft(node.left);
}
// Left Left Heavy
return this._rotateRight(node);
}
// Right Heavy
if (balance < -1) {
// Right Left Heavy
if (value < node.right.value) {
node.right = this._rotateRight(node.right);
}
// Right Right Heavy
return this._rotateLeft(node);
}
return node;
}
// ... 其他操作如删除、查找可以参照普通的BST进行实现,但需要加入平衡的操作。
}
##红黑树 红黑树是一种自平衡二叉搜索树,每个节点都有一个颜色属性,红色或黑色。红黑树必须满足以下属性:
- 节点是红色或黑色。
- 根节点是黑色。
- 所有叶子(通常为NIL或空节点)是黑色。
- 如果一个红色节点有子节点,那么子节点必须是黑色。
- 从任何节点到其所有后代叶子的路径都包含相同数量的黑色节点。
以下是一个简化版的红黑树实现:
const RED = true;
const BLACK = false;
class TreeNode {
constructor(value, color, left=null, right=null) {
this.value = value;
this.color = color; // 默认红色
this.left = left;
this.right = right;
this.parent = null;
}
}
class RedBlackTree {
constructor() {
this.NIL_LEAF = new TreeNode(null, BLACK);
this.root = this.NIL_LEAF;
}
isRed(node) {
return node.color === RED;
}
rotateLeft(node) {
let tmp = node.right;
node.right = tmp.left;
if (tmp.left !== this.NIL_LEAF) {
tmp.left.parent = node;
}
tmp.parent = node.parent;
if (!node.parent) {
this.root = tmp;
} else if (node === node.parent.left) {
node.parent.left = tmp;
} else {
node.parent.right = tmp;
}
tmp.left = node;
node.parent = tmp;
}
rotateRight(node) {
let tmp = node.left;
node.left = tmp.right;
if (tmp.right !== this.NIL_LEAF) {
tmp.right.parent = node;
}
tmp.parent = node.parent;
if (!node.parent) {
this.root = tmp;
} else if (node === node.parent.left) {
node.parent.left = tmp;
} else {
node.parent.right = tmp;
}
tmp.right = node;
node.parent = tmp;
}
insert(value) {
let node = new TreeNode(value, RED, this.NIL_LEAF, this.NIL_LEAF);
this._insertNode(node);
}
_insertNode(node) {
// ... 标准的BST插入操作,同时维护父节点信息
// 调整红黑树平衡
this.fixInsert(node);
}
fixInsert(node) {
let parentNode;
while (node !== this.root && this.isRed(node.parent)) {
parentNode = node.parent.parent;
if (parentNode.left === node.parent) {
let uncle = parentNode.right;
if (this.isRed(uncle)) {
// Case 1: 叔叔节点也是红色
node.parent.color = BLACK;
uncle.color = BLACK;
parentNode.color = RED;
node = parentNode;
} else {
if (node === node.parent.right) {
// Case 2: node是一个右子节点
node = node.parent;
this.rotateLeft(node);
}
// Case 3: node是一个左子节点
node.parent.color = BLACK;
parentNode.color = RED;
this.rotateRight(parentNode);
}
} else {
// ... 上面代码的镜像操作,此时node在右子树
}
}
this.root.color = BLACK;
}
// ... 还有其他操作,如删除、查找等
}