-
Notifications
You must be signed in to change notification settings - Fork 0
AVL树
兰亭古墨 edited this page Aug 25, 2021
·
1 revision
Adelson-Velskii-Landi 树( AVL 树)
AVL树是一种自平衡树。添加或移除节点时, AVL树会尝试保持自平衡。任意一个节点(不论深度)的左子树和右子树高度最多相差 1。添加或移除节点时, AVL树会尽可能尝试转换为完全树。
import { defaultCompare, Compare } from "@/index";
import { BalanceFactor } from "@/utils/index";
import { BinarySearchTree } from "./19.BinarySearchTree";
import { Node } from "./19.BinarySearchTree";
export class AVLTree extends BinarySearchTree {
constructor(compareFn = defaultCompare) {
super(compareFn);
this.root = null;
}
// 获取节点高度
getNodeHeight(node) {
if (node == null) {
return -1;
}
return (
Math.max(this.getNodeHeight(node.left), this.getNodeHeight(node.right)) +
1
);
}
// 获取平衡因子
getBalanceFactor(node) {
const heightDifference =
this.getNodeHeight(node.left) - this.getNodeHeight(node.right);
switch (heightDifference) {
case -2:
return BalanceFactor.UNBALANCED_RIGHT;
case -1:
return BalanceFactor.SLIGHTLY_UNBALANCED_RIGHT;
case 1:
return BalanceFactor.SLIGHTLY_UNBALANCED_LEFT;
case 2:
return BalanceFactor.UNBALANCED_LEFT;
default:
return BalanceFactor.BALANCED;
}
}
// 左-左:向右的单旋转。左侧失衡
rotationLL(node) {
const tmp = node.left;
node.left = tmp.right;
tmp.right = node;
return tmp;
}
// 右-右(RR):向左的单旋转。右侧失衡
rotationRR(node) {
const tmp = node.right;
node.right = tmp.left;
tmp.left = node;
return tmp;
}
// 左-右(LR):向右的双旋转
// 左侧子节点的高度大于右侧子节点的高度,并且左侧子节点右侧较重
rotationLR(node) {
node.left = this.rotationRR(node.left);
return this.rotationLL(node);
}
// 右-左(RL):向左的双旋转
// 右侧子节点的高度大于左侧子节点的高度,并且右侧子节点左侧较重
rotationRL(node) {
node.right = this.rotationLL(node.right);
return this.rotationRR(node);
}
insert(key) {
debugger
this.root = this.insertNode(this.root, key);
}
insertNode(node, key) {
// 像在 BST 树中一样插入节点
if (node == null) {
return new Node(key);
} else if (this.compareFn(key, node.key) === Compare.LESS_THAN) {
node.left = this.insertNode(node.left, key);
} else if (this.compareFn(key, node.key) === Compare.BIGGER_THAN) {
node.right = this.insertNode(node.right, key);
} else {
return node; // 重复的键
}
// 如果需要,将树进行平衡操作
const balanceFactor = this.getBalanceFactor(node);
if (balanceFactor === BalanceFactor.UNBALANCED_LEFT) {
if (this.compareFn(key, node.left.key) === Compare.LESS_THAN) {
node = this.rotationLL(node);
} else {
return this.rotationLR(node);
}
}
if (balanceFactor === BalanceFactor.UNBALANCED_RIGHT) {
if (this.compareFn(key, node.right.key) === Compare.BIGGER_THAN) {
node = this.rotationRR(node);
} else {
return this.rotationRL(node);
}
}
return node;
}
removeNode(node, key) {
node = super.removeNode(node, key);
if (node == null) {
return node; // null,不需要进行平衡
}
// 检测树是否平衡
const balanceFactor = this.getBalanceFactor(node);
if (balanceFactor === BalanceFactor.UNBALANCED_LEFT) {
const balanceFactorLeft = this.getBalanceFactor(node.left);
if (balanceFactorLeft === BalanceFactor.SLIGHTLY_UNBALANCED_LEFT) {
return this.rotationLL(node);
}
if (balanceFactorLeft === BalanceFactor.SLIGHTLY_UNBALANCED_RIGHT) {
return this.rotationLR(node.left);
}
}
if (balanceFactor === BalanceFactor.UNBALANCED_RIGHT) {
const balanceFactorRight = this.getBalanceFactor(node.right);
if (balanceFactorRight === BalanceFactor.SLIGHTLY_UNBALANCED_RIGHT) {
return this.rotationRR(node);
}
if (balanceFactorRight === BalanceFactor.SLIGHTLY_UNBALANCED_LEFT) {
return this.rotationRL(node.right);
}
}
return node;
}
}
这里是 footer