pisces-data-structure
Version:
164 lines (120 loc) • 4.4 kB
text/typescript
/**
* AVL树
*/
import type { IAVLTreeNode, IAVLTree } from "../../../types";
import { BinarySearchTreeNode, BinarySearchTree } from "../index";
// AVL树节点类
class AVLTreeNode<T = any> extends BinarySearchTreeNode<T> implements IAVLTreeNode<T> {
left: AVLTreeNode<T> | null = null;
right: AVLTreeNode<T> | null = null;
parent: AVLTreeNode<T> | null = null;
private getHeight(): number {
const _leftChildHeight = this.left ? this.left.getHeight() : 0;
const _rightChildHeight = this.right ? this.right.getHeight() : 0;
return Math.max(_leftChildHeight, _rightChildHeight) + 1;
}
public getBalanceFactor(): number {
const _leftChildHeight = this.left ? this.left.getHeight() : 0;
const _rightChildHeight = this.right ? this.right.getHeight() : 0;
return _leftChildHeight - _rightChildHeight;
}
public get isBalanced(): boolean {
const _balanceFactor = this.getBalanceFactor();
return _balanceFactor >= -1 && _balanceFactor <= 1;
}
get higherChildNode(): AVLTreeNode<T> | null {
const _leftChildHeight = this.left ? this.left.getHeight() : 0;
const _rightChildHeight = this.right ? this.right.getHeight() : 0;
if (_leftChildHeight > _rightChildHeight) {
return this.left;
} else if (_rightChildHeight > _leftChildHeight) {
return this.right;
} else {
return this.isLeftChild ? this.left : this.right;
}
}
public rotateRight() {
const _pivot = this.left!;
const _isLeftChild = this.isLeftChild;
const _isRightChild = this.isRightChild;
_pivot.parent = this.parent;
this.left = _pivot.right;
if (_pivot.right) {
_pivot.right.parent = this;
}
_pivot.right = this;
this.parent = _pivot;
if (_pivot.parent) {
if (_isLeftChild) {
_pivot.parent.left = _pivot;
} else if (_isRightChild) {
_pivot.parent.right = _pivot;
}
}
return _pivot;
}
rotateLeft() {
const _pivot = this.right!;
const _isLeftChild = this.isLeftChild;
const _isRightChild = this.isRightChild;
_pivot.parent = this.parent;
this.right = _pivot.left;
if (_pivot.left) {
_pivot.left.parent = this;
}
_pivot.left = this;
this.parent = _pivot;
if (_pivot.parent) {
if (_isLeftChild) {
_pivot.parent.left = _pivot;
} else if (_isRightChild) {
_pivot.parent.right = _pivot;
}
}
return _pivot;
}
}
// AVL数类
class AVLTree<T = any> extends BinarySearchTree<T> implements IAVLTree<T> {
protected root: AVLTreeNode<T> | null = null;
private rebalance(grandParent: AVLTreeNode<T>) {
const _parent = grandParent.higherChildNode!;
const _current = _parent.higherChildNode!;
let _resultNode: AVLTreeNode<T> | null = null;
if (_parent.isLeftChild) {
if (_current.isLeftChild) {
_resultNode = grandParent.rotateRight();
} else {
_parent.rotateLeft();
_resultNode = grandParent.rotateRight();
}
} else {
if (_current.isLeftChild) { // RL情况
_parent.rotateRight();
_resultNode = grandParent.rotateLeft();
} else {
_resultNode = grandParent.rotateLeft();
}
}
if (!_resultNode.parent) {
this.root = _resultNode;
}
}
protected createTreeNode(value: T): BinarySearchTreeNode<T> {
return new AVLTreeNode(value);
}
protected checkBalance(treeNode: AVLTreeNode<T>, actionType = 'insert'): void {
let _current = treeNode.parent;
while (_current) {
if (!_current.isBalanced) {
this.rebalance(_current);
if (actionType === 'insert') break;
}
_current = _current.parent;
}
}
}
export {
AVLTreeNode,
AVLTree,
};