AVL树
AVL
2023-09-11 14:15:01 时间
在计算机科学中,一个AVL树(由Adelson-Velsky和Landis命名)是一个自平衡二叉查找树。AVL树是首次被发明的拥有自平衡特性的数据结构。在一个AVL树中,任何一个节点的两个子树的高度差不会超过1,也就是<=1;如果它们的高度差超过了1,就会触发平衡操作来修复其特性。查找,插入和删除的平均和最坏时间复杂度都是O(logn),n是树中节点数目。插入和删除操作可能会需要通过一次或多次树的旋转来重新平衡。
下图的动画展示了插入多个节点到一个AVL树时的情况。包括了,左旋转,右旋转,左右旋转和右左旋转。
展示平衡因子的AVL树(绿色是平衡因子)
AVL树旋转操作
左左旋转
右右旋转
左右旋转
右左旋转
代码实现
AvlTree.js
import BinarySearchTree from '../binary-search-tree/BinarySearchTree'; export default class AvlTree extends BinarySearchTree {//AVL树类,继承自二叉搜索树 /** * @param {*} value */ insert(value) {//往AVL树中插入新节点 // Do the normal BST insert. super.insert(value);//调用父类二叉搜索书的插入方法插入节点 // Let's move up to the root and check balance factors along the way. //移除根节点沿着顺序检查平衡因子 let currentNode = this.root.find(value);//找到刚才被插入的节点 while (currentNode) { this.balance(currentNode);//调用balance方法使当前节点平衡,然后当前节点赋值为父节点,继续循环 currentNode = currentNode.parent; } } /** * @param {*} value * @return {boolean} */ remove(value) {//在AVL树中删除节点 // Do standard BST removal. super.remove(value);//调用父类二叉搜索树的删除方法删除节点 // Balance the tree starting from the root node. this.balance(this.root);//从根节点开始做平衡操作 } /** * @param {BinarySearchTreeNode} node */ balance(node) { // If balance factor is not OK then try to balance the node. if (node.balanceFactor > 1) {//如果当前节点的平衡因子大于1了,说明不平衡了 // Left rotation. if (node.left.balanceFactor > 0) {//当前节点的左子节点平衡因子大于0,做左左旋转 // Left-Left rotation this.rotateLeftLeft(node); } else if (node.left.balanceFactor < 0) {//当前节点的左子节点平衡因子小于0,做左右旋转 // Left-Right rotation. this.rotateLeftRight(node); } } else if (node.balanceFactor < -1) {//当前节点的平衡因子小于-1 // Right rotation. if (node.right.balanceFactor < 0) {//当前节点的右子节点平衡因子小于0,做右右旋转 // Right-Right rotation this.rotateRightRight(node); } else if (node.right.balanceFactor > 0) {//当前节点的右子节点平衡因子大于0,做右左旋转 // Right-Left rotation. this.rotateRightLeft(node); } } } /** * @param {BinarySearchTreeNode} rootNode */ rotateLeftLeft(rootNode) {//左左旋转 // Detach left node from root node. const leftNode = rootNode.left;//rootNode的左子节点 rootNode.setLeft(null);//rootNode的左子节点设置为空 // Make left node to be a child of rootNode's parent. if (rootNode.parent) {//如果rootNode有父节点 rootNode.parent.setLeft(leftNode);//给rootNode的父节点设置左子节点为rootNode的左子节点 } else if (rootNode === this.root) { //如果rooNode本身就是树的根节点,就将rootNode的左子节点设置为当前树的根节点 // If root node is root then make left node to be a new root. this.root = leftNode; } // If left node has a right child then detach it and // attach it as a left child for rootNode. if (leftNode.right) {//如果rootNode的左子节点有右子节点,就分离它,将它作为rootNode的左子节点连接 rootNode.setLeft(leftNode.right); } // Attach rootNode to the right of leftNode. leftNode.setRight(rootNode);//将rootNode作为其左子节点的右子节点 } /** * @param {BinarySearchTreeNode} rootNode */ rotateLeftRight(rootNode) {//左右旋转 // Detach left node from rootNode since it is going to be replaced. const leftNode = rootNode.left;//rootNode节点的左子节点 rootNode.setLeft(null);//设置rootNode的左子节点为空 // Detach right node from leftNode. const leftRightNode = leftNode.right;//rootNode的左子节点的右子节点 leftNode.setRight(null);//设置左子节点的右节点为空 // Preserve leftRightNode's left subtree. if (leftRightNode.left) {//如果rootNode的左子节点的右子节点拥有左子节点 //就设置rootNode的左子节点的右子节点为如果rootNode的左子节点的右子节点的左子节点 leftNode.setRight(leftRightNode.left); leftRightNode.setLeft(null);//rootNode的左子节点的右子节点的左子节点设置为空 } // Attach leftRightNode to the rootNode. rootNode.setLeft(leftRightNode);//rootNode设置左子节点为rootNode的左子节点的右子节点 // Attach leftNode as left node for leftRight node. leftRightNode.setLeft(leftNode);//rootNode的左子节点的右子节点设置左子节点为rootNode的左子节点 // Do left-left rotation. this.rotateLeftLeft(rootNode);//对rootNode进行左左旋转操作 } /** * @param {BinarySearchTreeNode} rootNode */ rotateRightLeft(rootNode) {//右左旋转 // Detach right node from rootNode since it is going to be replaced. const rightNode = rootNode.right;//rootNode的右子节点 rootNode.setRight(null);//设置rootNode的右子节点为空 // Detach left node from rightNode. const rightLeftNode = rightNode.left;//rootNode的右子节点的左子节点 rightNode.setLeft(null);//设置rootNode的右子节点的左子节点为空 if (rightLeftNode.right) {//如果rootNode的右子节点的左子节点拥有右子节点 rightNode.setLeft(rightLeftNode.right);//设置rootNode的右节点的左子节点为rootNode的右子节点的左子节点的右子节点 rightLeftNode.setRight(null);//rootNode的右子节点的左子节点的右子节点设置为空 } // Attach rightLeftNode to the rootNode. rootNode.setRight(rightLeftNode);//设置rootNode的哦右子节点为rootNode的右子节点的左子节点 // Attach rightNode as right node for rightLeft node. rightLeftNode.setRight(rightNode);//设置rootNode的右子节点的左子节点的右子节点为rootNode的右子节点 // Do right-right rotation. this.rotateRightRight(rootNode);//对rootNode进行右右旋转 } /** * @param {BinarySearchTreeNode} rootNode */ rotateRightRight(rootNode) {//右右旋转 // Detach right node from root node. const rightNode = rootNode.right;//rootNode的右子节点 rootNode.setRight(null);//设置rootNode的右子节点为空 // Make right node to be a child of rootNode's parent. if (rootNode.parent) {//如果rootNode拥有父节点,就设置rootNode的父节点的右子节点为rootNode的右子节点 rootNode.parent.setRight(rightNode); } else if (rootNode === this.root) {//如果rootNode本身就是根节点,就像根节点设置为rootNode的右子节点 // If root node is root then make right node to be a new root. this.root = rightNode; } // If right node has a left child then detach it and // attach it as a right child for rootNode. if (rightNode.left) {//如果rootNode的右子节点拥有左子节点,就设置rootNode的右子节点为rootNode的右子节点的左子节点 rootNode.setRight(rightNode.left); } // Attach rootNode to the left of rightNode. rightNode.setLeft(rootNode);//rootNode的右子节点的左子节点设置为rootNode } }
相关文章
- 数据结构_平衡二叉树(AVL树)
- AVL Tree
- pat(A) 1066. Root of AVL Tree
- C++模板实现的AVL树
- AVL平衡树的插入例程
- 有序表TreeMap/TreeSet底层实现:AVL树、傻逼树SBT、红黑树RBT、跳表SkipMap失衡类型
- C#,自平衡二叉查找树(AVL Tree)的算法与源代码
- 1123 Is It a Complete AVL Tree (30 分)【难度: 难 / 平衡树 未完成】
- 1066 Root of AVL Tree (25 分)【难 / 知识点: 平衡树 未完成】
- 数据结构之AVL树
- 面试题:为什么用红黑树不用普通的AVL树
- 总结下各种常见树形结构的定义及特点(二叉树、AVL树、红黑树、Trie树、B树、B+树)
- 红黑树和AVL树(平衡二叉树)区别
- 【C++】AVL树,平衡二叉树详细解析
- 平衡二叉树(AVL树)
- 浅谈AVL树,红黑树,B树,B+树原理及应用
- AVL树,红黑树,B树,B+树,Trie树都分别应用在哪些现实场景中?
- AVL树
- 看动画学算法之:平衡二叉搜索树AVL Tree
- 数据结构 | AVL 我现在命令你 快变回你原来的样子
- 6.3 AVL树
- 数据结构中常见的树(BST二叉搜索树、AVL平衡二叉树、RBT红黑树、B-树、B+树、B*树)(转)
- 数据结构与算法——AVL树类的C++实现
- AVL树、红黑树、B树、B+树、Trie树都分别应用在哪些现实场景中?
- 【Python数据结构】——二叉平衡树AVL(查找、构建、删除、插入、打印、遍历)
- 数据结构-AVL树
- 数据结构-AVL树
- 1066 Root of AVL Tree
- 1123 Is It a Complete AVL Tree
- 算法补天系列之有序表的四种实现方式——AVL树,SB树,红黑树,跳表(重点)介绍说明