返回
JavaScript排序二叉树的奇妙世界:巧妙实现与实战应用
前端
2023-10-28 08:16:16
技术博文:《JavaScript中的排序二叉树:实现和应用》
排序二叉树,也称为二叉搜索树,是一种特殊的二叉树,其中每个节点都存储着一个键值,并且该键值小于其左子树的所有键值,大于其右子树的所有键值。这种性质使得排序二叉树在查找、插入和删除操作中具有高效的性能。
在JavaScript中实现排序二叉树,我们可以采用面向对象的编程方式。首先,我们定义一个Node类,该类将表示排序二叉树中的每个节点。Node类包含三个属性:键值(key)、左子节点(left)和右子节点(right)。
class Node {
constructor(key) {
this.key = key;
this.left = null;
this.right = null;
}
}
接下来,我们定义一个BinarySearchTree类,该类将实现排序二叉树的基本操作。BinarySearchTree类包含一个根节点(root)属性,该属性指向排序二叉树的根节点。
class BinarySearchTree {
constructor() {
this.root = null;
}
插入
为了在排序二叉树中插入一个新节点,我们需要从根节点开始,并根据键值的大小决定将新节点插入到左子树还是右子树。如果要插入的键值小于当前节点的键值,则将新节点插入到左子树中。否则,将新节点插入到右子树中。
insert(key) {
const newNode = new Node(key);
if (this.root === null) {
this.root = newNode;
} else {
this._insert(newNode, this.root);
}
}
_insert(newNode, currentNode) {
if (newNode.key < currentNode.key) {
if (currentNode.left === null) {
currentNode.left = newNode;
} else {
this._insert(newNode, currentNode.left);
}
} else {
if (currentNode.right === null) {
currentNode.right = newNode;
} else {
this._insert(newNode, currentNode.right);
}
}
}
查找
为了在排序二叉树中查找一个键值,我们需要从根节点开始,并根据键值的大小决定是向左子树还是向右子树查找。如果要查找的键值等于当前节点的键值,则查找成功,返回该节点。否则,继续在左子树或右子树中查找。
find(key) {
if (this.root === null) {
return null;
} else {
return this._find(key, this.root);
}
}
_find(key, currentNode) {
if (key === currentNode.key) {
return currentNode;
} else if (key < currentNode.key) {
if (currentNode.left === null) {
return null;
} else {
return this._find(key, currentNode.left);
}
} else {
if (currentNode.right === null) {
return null;
} else {
return this._find(key, currentNode.right);
}
}
}
删除
删除排序二叉树中的一个节点是一个比较复杂的操作。首先,我们需要找到要删除的节点。然后,根据该节点的情况,决定是直接删除该节点,还是用其左子树或右子树的最小或最大节点替换该节点。
remove(key) {
if (this.root === null) {
return;
} else {
this._remove(key, this.root);
}
}
_remove(key, currentNode) {
if (key === currentNode.key) {
if (currentNode.left === null && currentNode.right === null) {
currentNode = null;
} else if (currentNode.left === null) {
currentNode = currentNode.right;
} else if (currentNode.right === null) {
currentNode = currentNode.left;
} else {
const smallestNode = this._findMin(currentNode.right);
currentNode.key = smallestNode.key;
this._remove(smallestNode.key, currentNode.right);
}
} else if (key < currentNode.key) {
if (currentNode.left === null) {
return;
} else {
this._remove(key, currentNode.left);
}
} else {
if (currentNode.right === null) {
return;
} else {
this._remove(key, currentNode.right);
}
}
}
_findMin(node) {
while (node.left !== null) {
node = node.left;
}
return node;
}
平衡
为了保持排序二叉树的平衡,我们可以采用各种平衡算法。最常用的平衡算法之一是红黑树算法。红黑树算法将每个节点标记为红色或黑色,并通过一系列规则来确保树的高度保持平衡。
class RedBlackTree {
constructor() {
this.root = null;
}
// 插入操作
insert(key) {
const newNode = new Node(key);
this._insert(newNode);
this._fixInsert(newNode);
}
_insert(newNode) {
if (this.root === null) {
this.root = newNode;
} else {
this._insertHelper(newNode, this.root);
}
}
_insertHelper(newNode, currentNode) {
if (newNode.key < currentNode.key) {
if (currentNode.left === null) {
currentNode.left = newNode;
} else {
this._insertHelper(newNode, currentNode.left);
}
} else {
if (currentNode.right === null) {
currentNode.right = newNode;
} else {
this._insertHelper(newNode, currentNode.right);
}
}
}
// 修复插入后的红黑树
_fixInsert(newNode) {
while (newNode !== this.root && newNode.parent.color === 'red') {
if (newNode.parent === newNode.parent.parent.left) {
const uncle = newNode.parent.parent.right;
if (uncle.color === 'red') {
newNode.parent.color = 'black';
uncle.color = 'black';
newNode.parent.parent.color = 'red';
newNode = newNode.parent.parent;
} else {
if (newNode === newNode.parent.right) {
newNode = newNode.parent;
this._leftRotate(newNode);
}
newNode.parent.color = 'black';
newNode.parent.parent.color = 'red';
this._rightRotate(newNode.parent.parent);
}
} else {
const uncle = newNode.parent.parent.left;
if (uncle.color === 'red') {
newNode.parent.color = 'black';
uncle.color = 'black';
newNode.parent.parent.color = 'red';
newNode = newNode.parent.parent;
} else {
if (newNode === newNode.parent.left) {
newNode = newNode.parent;
this._rightRotate(newNode);
}
newNode.parent.color = 'black';
newNode.parent.parent.color = 'red';
this._leftRotate(newNode.parent.parent);
}
}
}
this.root.color = 'black';
}
// 左旋操作
_leftRotate(node) {
const rightChild = node.right;
node.right = rightChild.left;
if (rightChild.left !== null) {
rightChild.left.parent = node;
}
rightChild.parent = node.parent;
if (node.parent === null) {
this.root = rightChild;
} else if