AVL 树
在计算机科学中,AVL 树(以发明者 Adelson-Velsky 和 Landis 命名)是一种自平衡的二叉搜索树。它是第一个被发明出来的这种数据结构。在 AVL 树中,任何节点的两个子树的高度最多相差一;如果在任何时候它们相差超过一,就会进行重新平衡以恢复这个属性。查找、插入和删除在平均和最坏情况下都需要 O(log n)的时间,其中 n 是操作之前树中节点的数量。插入和删除可能需要对树进行一个或多个树旋转进行重新平衡。
动画显示将几个元素插入到 AVL 树中。它包括左旋、右旋、左右旋和右左旋。

带有平衡因子(绿色)的 AVL 树

AVL Tree Rotations
Left-Left Rotation

Right-Right Rotation

Left-Right Rotation

Right-Left Rotation

AvlTree
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
| export default class AvlTree extends BinarySearchTree {
insert(value) { super.insert(value);
let currentNode = this.root.find(value); while (currentNode) { this.balance(currentNode); currentNode = currentNode.parent; } }
remove(value) { super.remove(value);
this.balance(this.root); }
balance(node) { if (node.balanceFactor > 1) { if (node.left.balanceFactor > 0) { this.rotateLeftLeft(node); } else if (node.left.balanceFactor < 0) { this.rotateLeftRight(node); } } else if (node.balanceFactor < -1) { if (node.right.balanceFactor < 0) { this.rotateRightRight(node); } else if (node.right.balanceFactor > 0) { this.rotateRightLeft(node); } } }
rotateLeftLeft(rootNode) { const leftNode = rootNode.left; rootNode.setLeft(null);
if (rootNode.parent) { rootNode.parent.setLeft(leftNode); } else if (rootNode === this.root) { this.root = leftNode; }
if (leftNode.right) { rootNode.setLeft(leftNode.right); }
leftNode.setRight(rootNode); }
rotateLeftRight(rootNode) { const leftNode = rootNode.left; rootNode.setLeft(null);
const leftRightNode = leftNode.right; leftNode.setRight(null);
if (leftRightNode.left) { leftNode.setRight(leftRightNode.left); leftRightNode.setLeft(null); }
rootNode.setLeft(leftRightNode);
leftRightNode.setLeft(leftNode);
this.rotateLeftLeft(rootNode); }
rotateRightLeft(rootNode) { const rightNode = rootNode.right; rootNode.setRight(null);
const rightLeftNode = rightNode.left; rightNode.setLeft(null);
if (rightLeftNode.right) { rightNode.setLeft(rightLeftNode.right); rightLeftNode.setRight(null); }
rootNode.setRight(rightLeftNode);
rightLeftNode.setRight(rightNode);
this.rotateRightRight(rootNode); }
rotateRightRight(rootNode) { const rightNode = rootNode.right; rootNode.setRight(null);
if (rootNode.parent) { rootNode.parent.setRight(rightNode); } else if (rootNode === this.root) { this.root = rightNode; }
if (rightNode.left) { rootNode.setRight(rightNode.left); }
rightNode.setLeft(rootNode); } }
|