class Node {
constructor(value) {
this
.value = value;
this
.left =
null
;
this
.right =
null
;
this
.height = 1;
}
}
class AVLTree {
constructor() {
this
.root =
null
;
}
height(node) {
if
(!node)
return
0;
return
node.height;
}
balanceFactor(node) {
if
(!node)
return
0;
return
this
.height(node.left) -
this
.height(node.right);
}
rotateRight(node) {
const leftNode = node.left;
const rightOfLeftNode = leftNode.right;
leftNode.right = node;
node.left = rightOfLeftNode;
node.height = Math.max(
this
.height(node.left),
this
.height(node.right)) + 1;
leftNode.height =
Math.max(
this
.height(leftNode.left),
this
.height(leftNode.right)) + 1;
return
leftNode;
}
rotateLeft(node) {
const rightNode = node.right;
const leftOfRightNode = rightNode.left;
rightNode.left = node;
node.right = leftOfRightNode;
node.height = Math.max(
this
.height(node.left),
this
.height(node.right)) + 1;
rightNode.height =
Math.max(
this
.height(rightNode.left),
this
.height(rightNode.right)) + 1;
return
rightNode;
}
insert(value) {
this
.root =
this
.insertNode(
this
.root, value);
}
insertNode(node, value) {
if
(!node) {
return
new
Node(value);
}
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 = Math.max(
this
.height(node.left),
this
.height(node.right)) + 1;
const balance =
this
.balanceFactor(node);
if
(balance > 1 && value < node.left.value) {
return
this
.rotateRight(node);
}
if
(balance > 1 && value > node.left.value) {
node.left =
this
.rotateLeft(node.left);
return
this
.rotateRight(node);
}
if
(balance < -1 && value > node.right.value) {
return
this
.rotateLeft(node);
}
if
(balance < -1 && value < node.right.value) {
node.right =
this
.rotateRight(node.right);
return
this
.rotateLeft(node);
}
return
node;
}
search(value) {
return
this
.searchNode(
this
.root, value);
}
searchNode(node, value) {
if
(!node)
return
null
;
if
(value < node.value) {
return
this
.searchNode(node.left, value);
}
else
if
(value > node.value) {
return
this
.searchNode(node.right, value);
}
else
{
return
node;
}
}
delete
(value) {
this
.root =
this
.deleteNode(
this
.root, value);
}
deleteNode(node, value) {
if
(!node) {
return
null
;
}
if
(value < node.value) {
node.left =
this
.deleteNode(node.left, value);
}
else
if
(value > node.value) {
node.right =
this
.deleteNode(node.right, value);
}
else
{
if
(!node.left && !node.right) {
node =
null
;
}
else
if
(!node.left) {
node = node.right;
}
else
if
(!node.right) {
node = node.left;
}
else
{
const minNode =
this
.findMinNode(node.right);
node.value = minNode.value;
node.right =
this
.deleteNode(node.right, minNode.value);
}
}
if
(!node)
return
null
;
node.height = Math.max(
this
.height(node.left),
this
.height(node.right)) + 1;
const balance =
this
.balanceFactor(node);
if
(balance > 1 &&
this
.balanceFactor(node.left) >= 0) {
return
this
.rotateRight(node);
}
if
(balance > 1 &&
this
.balanceFactor(node.left) < 0) {
node.left =
this
.rotateLeft(node.left);
return
this
.rotateRight(node);
}
if
(balance < -1 &&
this
.balanceFactor(node.right) <= 0) {
return
this
.rotateLeft(node);
}
if
(balance < -1 &&
this
.balanceFactor(node.right) > 0) {
node.right =
this
.rotateRight(node.right);
return
this
.rotateLeft(node);
}
return
node;
}
findMinNode(node) {
while
(node && node.left) {
node = node.left;
}
return
node;
}
}
const tree =
new
AVLTree();
tree.insert(4);
tree.insert(2);
tree.insert(7);
tree.insert(1);
tree.insert(3);
tree.insert(5);
tree.insert(8);
tree.insert(6);
console.log(tree.search(5));
tree.
delete
(7);
console.log(tree.search(7));