返回
技术指南:揭秘前端算法入门之路(手撕AVL树)
前端
2024-01-27 16:54:41
二叉排序树(Binary Search Tree,BST),也称二叉查找树或二叉搜索树,是一种常见的树形数据结构,具有以下特性:
- 左子树上的所有键值小于其父节点的键值。
- 右子树上的所有键值大于其父节点的键值。
- 左、右子树也是二叉排序树。
二叉排序树常用于解决与排名相关的检索需求,例如查找某个元素在集合中的位置或查找某个元素的前驱或后继。
AVL树(Adelson-Velsky and Landis Tree)是平衡二叉排序树的一种,其特点是左右子树的高度差至多为1,这样可以保证树的插入和删除操作的时间复杂度为O(log n)。
AVL树的插入和删除操作都比较复杂,但可以保证树的平衡性。AVL树常用于需要频繁插入和删除元素的场景。
现在让我们手撕一个AVL树。
1. AVL树的节点结构
class AVLNode {
constructor(value) {
this.value = value;
this.left = null;
this.right = null;
this.height = 1;
}
}
2. 计算节点的高度
AVLNode.prototype.getHeight = function () {
return Math.max(this.left ? this.left.height : 0, this.right ? this.right.height : 0) + 1;
};
3. 计算节点的平衡因子
AVLNode.prototype.getBalanceFactor = function () {
return (this.left ? this.left.height : 0) - (this.right ? this.right.height : 0);
};
4. 插入元素
AVLTree.prototype.insert = function (value) {
const newNode = new AVLNode(value);
this.root = this._insert(newNode, this.root);
};
AVLTree.prototype._insert = function (newNode, node) {
if (!node) {
return newNode;
}
if (value < node.value) {
node.left = this._insert(newNode, node.left);
} else if (value > node.value) {
node.right = this._insert(newNode, node.right);
} else {
throw new Error('Duplicate value');
}
node.height = node.getHeight();
const balanceFactor = node.getBalanceFactor();
if (balanceFactor > 1) {
if (value < node.left.value) {
return this._rightRotate(node);
} else {
return this._leftRightRotate(node);
}
} else if (balanceFactor < -1) {
if (value > node.right.value) {
return this._leftRotate(node);
} else {
return this._rightLeftRotate(node);
}
}
return node;
};
5. 删除元素
AVLTree.prototype.remove = function (value) {
this.root = this._remove(value, this.root);
};
AVLTree.prototype._remove = function (value, node) {
if (!node) {
return null;
}
if (value < node.value) {
node.left = this._remove(value, node.left);
} else if (value > node.value) {
node.right = this._remove(value, node.right);
} else {
if (!node.left) {
return node.right;
} else if (!node.right) {
return node.left;
} else {
const minValueNode = this._findMinValueNode(node.right);
node.value = minValueNode.value;
node.right = this._remove(minValueNode.value, node.right);
}
}
node.height = node.getHeight();
const balanceFactor = node.getBalanceFactor();
if (balanceFactor > 1) {
if (node.left.getBalanceFactor() < 0) {
return this._leftRightRotate(node);
} else {
return this._rightRotate(node);
}
} else if (balanceFactor < -1) {
if (node.right.getBalanceFactor() > 0) {
return this._rightLeftRotate(node);
} else {
return this._leftRotate(node);
}
}
return node;
};
6. 旋转操作
AVLTree.prototype._rightRotate = function (node) {
const leftNode = node.left;
node.left = leftNode.right;
leftNode.right = node;
node.height = node.getHeight();
leftNode.height = leftNode.getHeight();
return leftNode;
};
AVLTree.prototype._leftRotate = function (node) {
const rightNode = node.right;
node.right = rightNode.left;
rightNode.left = node;
node.height = node.getHeight();
rightNode.height = rightNode.getHeight();
return rightNode;
};
AVLTree.prototype._leftRightRotate = function (node) {
node.left = this._leftRotate(node.left);
return this._rightRotate(node);
};
AVLTree.prototype._rightLeftRotate = function (node) {
node.right = this._rightRotate(node.right);
return this._leftRotate(node);
};
7. 查询元素
AVLTree.prototype.search = function (value) {
return this._search(value, this.root);
};
AVLTree.prototype._search = function (value, node) {
if (!node) {
return null;
}
if (value < node.value) {
return this._search(value, node.left);
} else if (value > node.value) {
return this._search(value, node.right);
} else {
return node;
}
};
8. 查找最小值节点
AVLTree.prototype._findMinValueNode = function (node) {
while (node.left) {
node = node.left;
}
return node;
};
9. 查找最大值节点
AVLTree.prototype._findMaxValueNode = function (node) {
while (node.right) {
node = node.right;
}
return node;
};
10. 获取树的高度
AVLTree.prototype.getHeight = function () {
return this.root ? this.root.height : 0;
};