跳到主要内容

AVL 树(AVLTree)

最早发明的自平衡二叉搜索树之一

平衡因子(BlanceFactor)

某节点左右子树的高度差

特点

  • 每个节点的平衡因子只可能是-1、0、1(绝对值小于等于1,如果超过 1,称之为失衡)
  • 每个结点的左右子树高度差不超过 1
  • 搜索、添加、删除的时间复杂度是 O(logN)

核心代码

import { BlanceBinarySearchTree } from './blanceBinarySearchTree';
import { BinaryTreeNode } from './binaryTree';
export class AVLTreeNode<T> extends BinaryTreeNode<T> {
get leftHeight(): number {
return (this.left as AVLTreeNode<T>)?.height ?? 0;
}
get rightHeight(): number {
return (this.right as AVLTreeNode<T>)?.height ?? 0;
}
get balance() {
return Math.abs(this.leftHeight - this.rightHeight) <= 1;
}
get height() {
return Math.max(this.leftHeight, this.rightHeight) + 1;
}
/* istanbul ignore next */
constructor(
public val: T,
public parent: AVLTreeNode<T> | null = null,
public left: AVLTreeNode<T> | null = null,
public right: AVLTreeNode<T> | null = null
) {
super(val, parent, left, right);
}
}
export class AVLTree<T> extends BlanceBinarySearchTree<T> {
protected createNode(
val: T,
parent: BinaryTreeNode<T> | null = null,
left: BinaryTreeNode<T> | null = null,
right: BinaryTreeNode<T> | null = null
): BinaryTreeNode<T> {
return new AVLTreeNode(
val,
parent as AVLTreeNode<T> | null,
left as AVLTreeNode<T> | null,
right as AVLTreeNode<T> | null
);
}
protected afterAdd(node: AVLTreeNode<T>) {
let parent = node.parent;
while (parent !== null) {
if (!parent.balance) {
this.reBalance(parent);
break;
}
parent = parent.parent;
}
}
protected afterRemove(node: AVLTreeNode<T>) {
let parent = node.parent;
while (parent !== null) {
if (!parent.balance) this.reBalance(parent);
parent = parent.parent;
}
}
private reBalance(grandParent: AVLTreeNode<T>) {
const parent = this.getUnbalancedChild(grandParent);
const child = this.getUnbalancedChild(parent);
/**
左右旋转1
if (parent.isLeftChild) {
// L
if (child.isRightChild) this.rotateLeft(parent);
this.rotateRight(grandParent);
} else {
// R
if (child.isLeftChild) this.rotateRight(parent);
this.rotateLeft(grandParent);
}
*/
if (parent.isLeftChild) {
if (child.isLeftChild)
this.rotate(
grandParent,
parent,
child,
child.left,
child.right,
grandParent,
parent.right,
grandParent.right
);
else
this.rotate(
grandParent,
child,
parent,
parent.left,
child.left,
grandParent,
child.right,
grandParent.right
);
} else {
// R
if (child.isRightChild)
this.rotate(
grandParent,
parent,
grandParent,
grandParent.left,
parent.left,
child,
child.left,
child.right
);
else
this.rotate(
grandParent,
child,
grandParent,
grandParent.left,
child.left,
parent,
child.right,
parent.right
);
}
}
private getUnbalancedChild(node: AVLTreeNode<T>): AVLTreeNode<T> {
return (
node.leftHeight > node.rightHeight
? node.left
: node.leftHeight < node.rightHeight
? node.right
: node[node.childPosition]
) as AVLTreeNode<T>;
}
}