参考文章:
js实现avl树的构建和查找
https://cloud.tencent.com/developer/article/1538628
function AVLNode(value) {
this.value = value;
this.left = this.right = null;
this.height = 1;
}
// 获取节点高度: 该节点高度以经过的节点数作为avl树高度
function height(node) {
return node==null?0:node.height;
}
/**
* @description: RR-祖父节点左旋
* @param: 失衡节点
* @return: 新的根节点
*
* 25 => 30
* \ / \
* 30 25 35
* / \ \
* 28 35 28
*/
function RRrotate(unbalance) {
let newRoot = unbalance.right;
unbalance.right = newRoot.left;
newRoot.left = unbalance;
// 更新旋转节点的高度
unbalance.height = Math.max(height(unbalance.left), height(unbalance.right)) + 1;
newRoot.height = Math.max(height(newRoot.left), height(newRoot.right)) + 1;
return newRoot;
}
/**
* @description: LL-祖父节点右旋
* @param: 失衡节点
* @return: 新的根节点
*
* 25 => 15
* / / \
* 15 10 25
* / \ /
* 10 20 20
*/
function LLrotate(unbalance) {
let newRoot = unbalance.left;
unbalance.left = newRoot.right;
newRoot.right = unbalance;
// 更新高度
unbalance.height = Math.max(height(unbalance.left), height(unbalance.right)) + 1;
newRoot.height = Math.max(height(newRoot.left), height(newRoot.right)) + 1;
return newRoot;
}
/**
* @description: RL-父节点右旋,祖父节点左旋(相对30的节点描述)
* @param: 失衡节点(节点25为失衡节点)
* @return: 新的根节点
*
* 25 => 25 => 30
* \ \ / \
* 35 30 25 35
* / \
* 30 35
*/
function RLrotate(unbalance) {
unbalance.right = LLrotate(unbalance.right);
return RRrotate(unbalance);
}
/**
* @description: LR-父节点左旋,祖父节点右旋
* @param: 失衡节点
* @return: 新的根节点AVLNode
*
* 25 => 25 => 20
* / / / \
* 15 20 15 25
* \ /
* 20 15
*/
function LRrotate(unbalance) {
unbalance.left = RRrotate(unbalance.left);
return LLrotate(unbalance);
}
function insert(node, value) {
// 空节点,value生成新节点作为根节点
if(node == null) {
return new AVLNode(value);
}
if(value > node.value) {
// 在node节点的右子树上再递归插入
node.right = insert(node.right, value);
if(Math.abs(height(node.left) - height(node.right)) > 1) {
if(value > node.right.value) {//RR
node = RRrotate(node);
}else {//RL
node = RLrotate(node);
}
}
}else if(value < node.value) {
// 在node节点的左子树上再递归插入
node.left = insert(node.left, value);
if(Math.abs(height(node.left) - height(node.right)) > 1) {
if(value < node.left.value) {//LL
node = LLrotate(node);
}else {//LR
node = LRrotate(node);
}
}
}else {
// value == node.value
// 更新节点操作 或 不操作
}
// 插入新节点,更新高度
node.height = Math.max(height(node.left), height(node.right))+1;
return node;
}
function find(node, value) {
if(node==null) {
return null;
}
if(node.value == value) {
return node;
}
return find((value > node.value? node.right: node.left), value);
}
(function test() {
// 沙箱模式,在里面维护root节点
let i = 0;
let data = [];
while(i < 100) {
data.push(i++);
}
i = 0;
let root;
while(i < data.length) {
root = insert(root, data[i++]);
}
const queue = [root];
let current;
while(current = queue.shift()) {
console.log(current.value, height(current.right) - height(current.left));
queue.push(current.right);
queue.push(current.left);
}
console.log(root);
console.log(find(root ,99))
})();