当前位置:首页 > JavaScript

js实现avl树

2026-01-30 21:49:05JavaScript

AVL树的基本概念

AVL树是一种自平衡二叉搜索树,通过旋转操作保持树的平衡。每个节点的平衡因子(左子树高度减右子树高度)绝对值不超过1。插入或删除节点后,若平衡被破坏,需通过旋转恢复平衡。

节点结构

AVL树的节点需存储值、左右子节点指针和高度。以下为节点类的实现:

class AVLNode {
  constructor(value) {
    this.value = value;
    this.left = null;
    this.right = null;
    this.height = 1;
  }
}

平衡因子计算

通过左右子树高度差计算平衡因子:

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

节点高度更新

节点高度需动态更新,确保反映子树变化:

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

function updateHeight(node) {
  node.height = Math.max(getHeight(node.left), getHeight(node.right)) + 1;
}

旋转操作

四种旋转操作用于恢复平衡:

  • 右旋(LL型):处理左子树过深。

    function rightRotate(y) {
    const x = y.left;
    const T2 = x.right;
    
    x.right = y;
    y.left = T2;
    
    updateHeight(y);
    updateHeight(x);
    return x;
    }
  • 左旋(RR型):处理右子树过深。

    function leftRotate(x) {
    const y = x.right;
    const T2 = y.left;
    
    y.left = x;
    x.right = T2;
    
    updateHeight(x);
    updateHeight(y);
    return y;
    }
  • 左右旋(LR型):先左旋后右旋。

    function leftRightRotate(node) {
    node.left = leftRotate(node.left);
    return rightRotate(node);
    }
  • 右左旋(RL型):先右旋后左旋。

    function rightLeftRotate(node) {
    node.right = rightRotate(node.right);
    return leftRotate(node);
    }

插入节点

插入节点后检查平衡因子,必要时旋转:

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

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

  updateHeight(node);
  const balanceFactor = getBalanceFactor(node);

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

  return node;
}

删除节点

删除节点后同样需检查平衡:

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 = findMin(node.right);
      node.value = temp.value;
      node.right = deleteNode(node.right, temp.value);
    }
  }

  if (!node) return null;

  updateHeight(node);
  const balanceFactor = getBalanceFactor(node);

  // LL型
  if (balanceFactor > 1 && getBalanceFactor(node.left) >= 0) {
    return rightRotate(node);
  }
  // RR型
  if (balanceFactor < -1 && getBalanceFactor(node.right) <= 0) {
    return leftRotate(node);
  }
  // LR型
  if (balanceFactor > 1 && getBalanceFactor(node.left) < 0) {
    return leftRightRotate(node);
  }
  // RL型
  if (balanceFactor < -1 && getBalanceFactor(node.right) > 0) {
    return rightLeftRotate(node);
  }

  return node;
}

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

完整示例

以下为AVL树的完整使用示例:

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

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

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

// 使用示例
const tree = new AVLTree();
tree.insert(10);
tree.insert(20);
tree.insert(30); // 自动平衡
tree.delete(20); // 删除后仍保持平衡

注意事项

  • 每次插入或删除后需更新节点高度并检查平衡。
  • 旋转操作需正确处理子树指针,避免断裂。
  • 平衡因子计算需基于当前子树高度,确保准确性。

js实现avl树

标签: jsavl
分享给朋友:

相关文章

js实现拖拽

js实现拖拽

实现拖拽的基本步骤 通过监听鼠标事件(mousedown、mousemove、mouseup)实现拖拽功能。以下是核心代码逻辑: const draggableElement = document.…

js 实现倒计时

js 实现倒计时

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

js实现类

js实现类

JavaScript 实现类的几种方式 JavaScript 是一种基于原型的语言,但在 ES6 之后引入了 class 语法糖,使得实现类更加直观。以下是几种常见的实现方式: 使用构造函数 传统…

js实现延迟

js实现延迟

实现延迟的方法 在JavaScript中,实现延迟操作有多种方式,以下是几种常见的方法: 使用setTimeout函数 setTimeout是JavaScript中最常用的延迟执行方法。它接受一个…

js实现图表

js实现图表

在JavaScript中实现图表通常使用流行的图表库,以下是几种常见的方法和工具: 使用Chart.js Chart.js是一个简单灵活的库,适合快速生成响应式图表。安装方式包括CDN引入或npm安…

js实现抽奖

js实现抽奖

实现抽奖功能的基本思路 抽奖功能的核心是随机选择奖项并展示结果。可以通过数组存储奖项,利用随机数生成索引,最后通过动画增强用户体验。 准备奖项数据 定义一个数组存储奖项信息,每个奖项可以包含名称、图…