当前位置:首页 > JavaScript

js实现avl树

2026-03-01 12:54:45JavaScript

AVL树简介

AVL树是一种自平衡二叉搜索树,通过旋转操作保持左右子树高度差不超过1。其核心在于维护节点的平衡因子(左子树高度减右子树高度),并在插入或删除时通过四种旋转(左旋、右旋、左右旋、右左旋)恢复平衡。

节点类实现

class AVLNode {
  constructor(value) {
    this.value = value;
    this.left = null;
    this.right = null;
    this.height = 1; // 初始高度为1
  }
}

平衡因子计算

通过左右子树高度差计算当前节点的平衡因子:

function getBalanceFactor(node) {
  if (!node) return 0;
  return getHeight(node.left) - getHeight(node.right);
}

function getHeight(node) {
  return node ? node.height : 0;
}

旋转操作

右旋(LL型不平衡)

function rightRotate(y) {
  const x = y.left;
  const T2 = x.right;

  x.right = y;
  y.left = T2;

  y.height = Math.max(getHeight(y.left), getHeight(y.right)) + 1;
  x.height = Math.max(getHeight(x.left), getHeight(x.right)) + 1;

  return x; // 返回新的根节点
}

左旋(RR型不平衡)

function leftRotate(x) {
  const y = x.right;
  const T2 = y.left;

  y.left = x;
  x.right = T2;

  x.height = Math.max(getHeight(x.left), getHeight(x.right)) + 1;
  y.height = Math.max(getHeight(y.left), getHeight(y.right)) + 1;

  return y;
}

插入节点

插入后递归检查并修复平衡:

function insertNode(node, value) {
  if (!node) return new AVLNode(value);

  if (value < node.value) {
    node.left = insertNode(node.left, value);
  } else if (value > node.value) {
    node.right = insertNode(node.right, value);
  } else {
    return node; // 重复值不插入
  }

  node.height = 1 + Math.max(getHeight(node.left), getHeight(node.right));

  const balance = getBalanceFactor(node);

  // LL型
  if (balance > 1 && value < node.left.value) {
    return rightRotate(node);
  }
  // RR型
  if (balance < -1 && value > node.right.value) {
    return leftRotate(node);
  }
  // LR型
  if (balance > 1 && value > node.left.value) {
    node.left = leftRotate(node.left);
    return rightRotate(node);
  }
  // RL型
  if (balance < -1 && value < node.right.value) {
    node.right = rightRotate(node.right);
    return leftRotate(node);
  }

  return node;
}

删除节点

删除后需重新平衡:

js实现avl树

function deleteNode(node, value) {
  if (!node) return null;

  if (value < node.value) {
    node.left = deleteNode(node.left, value);
  } else if (value > node.value) {
    node.right = deleteNode(node.right, value);
  } else {
    if (!node.left || !node.right) {
      const temp = node.left || node.right;
      node = temp || null;
    } else {
      const temp = findMinNode(node.right);
      node.value = temp.value;
      node.right = deleteNode(node.right, temp.value);
    }
  }

  if (!node) return null;

  node.height = 1 + Math.max(getHeight(node.left), getHeight(node.right));
  const balance = getBalanceFactor(node);

  // 平衡修复逻辑与插入相同
  // ...

  return node;
}

function findMinNode(node) {
  while (node.left) node = node.left;
  return node;
}

完整示例

class AVLTree {
  constructor() {
    this.root = null;
  }

  insert(value) {
    this.root = insertNode(this.root, value);
  }

  delete(value) {
    this.root = deleteNode(this.root, value);
  }
}

复杂度分析

  • 插入/删除:时间复杂度为 O(log n),因每次操作最多需要从叶节点到根节点的路径上执行旋转。
  • 查询:与普通BST相同,为 O(log n)。

标签: jsavl
分享给朋友:

相关文章

js 实现倒计时

js 实现倒计时

实现倒计时的基本方法 使用 JavaScript 实现倒计时可以通过 setInterval 或 setTimeout 结合日期计算来完成。以下是两种常见实现方式。 使用 setInterval 实…

js实现乘

js实现乘

JavaScript 实现乘法运算 在 JavaScript 中实现乘法运算可以通过多种方式完成,包括基本运算符、函数封装以及高级算法(如大数乘法)。以下是几种常见方法: 使用基本乘法运算符 Jav…

js实现点击显示和隐藏

js实现点击显示和隐藏

实现点击显示和隐藏的JavaScript方法 使用classList.toggle切换类名 通过添加/移除CSS类控制元素的显示与隐藏,需提前在CSS中定义隐藏样式(如display: none)。…

js实现游标

js实现游标

使用JavaScript实现游标 在JavaScript中,可以通过操作DOM元素的cursor样式属性来实现自定义游标效果。以下是几种常见的实现方法: 修改默认鼠标指针样式 通过CSS的curso…

节流js实现

节流js实现

节流(Throttle)的实现原理 节流是一种限制函数执行频率的技术,确保函数在一定时间间隔内最多执行一次。适用于高频触发事件(如滚动、输入、窗口调整等)的场景。 基础实现方式 使用时间戳判断是否执…

js实现 功能

js实现 功能

在 JavaScript 中实现功能通常涉及多个关键步骤,具体取决于功能需求。以下是常见功能的实现方法和示例: 基本功能实现 使用函数封装逻辑是最直接的方式。例如,实现一个计算两数之和的函数: f…