数据结构与算法简记:AVL树

AVL树是一种自平衡二叉查找树,由Adelson-Velsky和Landis在1962年提出。在AVL树中,任何节点的两个子树高度最大差别为1,确保查找、插入和删除操作的平均和最坏时间复杂度为O(logN)。插入和删除操作后需通过旋转操作保持平衡,包括LL、RR、LR和RL四种情况。
摘要由CSDN通过智能技术生成

前面记录了二叉查找树,它在搜索方面的效率显而易见,可它也存在某种缺陷,假设我们连续插入较小或较大的数据,那么二叉查找树将会逐渐退变为一个线性结构,从而搜索就变为了线性查找,效率将会大打折扣。所以,我们需要一棵这样的树,它在插入新节点后,能够重新调整自己的结构,使左右恢复平衡。AVL树就符合这个条件。

AVL树是最先发明的自平衡二叉查找树,其得名于它的发明者 G.M. Adelson-Velsky 和 E.M. Landis,他们在 1962 年的论文 “An algorithm for the organization of information” 中发表了它。

在AVL树中任何节点的两个子树的高度最大差别为一,所以它也被称为高度平衡树,其查找、插入和删除在平均和最坏情况下都是O(logN)。

首先是创建AVL树:

我们可以从一个排序后的数组来初始化AVL树,这个过程不难,只需找到数组区间的中间元素,这个将作为树的根节点,同时这个节点将数组划分两个子区间,然后分别再取左右子区间中间元素,创建左右子树的根节点,同时继续划分子区间,如此进行下去。过程如下图所示:

然后是插入和移除节点,基本操作跟二叉查找树相似,不同的是这两个操作都需要重新平衡子树结构。

要使一棵树重新恢复平衡,我们需要对子树节点进行旋转操作,而旋转操作需要应对4种不同的情况,它们分别是:

LL: 即左左情况,此时需要对节点进行右旋转操作
RR: 即右右情况,此时需要对节点进行左旋转操作

以上这两种情况的旋转操作如下图所示:

还有两种相对复杂的情况:

LR: 即左右情况,此时需要先进行一次RR型旋转,再进行一次LL型旋转
RL: 即右做情况,此时需要先进行一次LL行旋转,再进行一次RR型旋转

下面两张图分别拆解了这两种情况的步骤:

下面分别是JS和C语言的实现代码:

JS描述:

//AVL树节点结构
function AVLTreeNode(data) {
   
  this.data = data;
  this.leftChild = null;
  this.rightChild = null;
  this.height = 0;
}

var AVLTreeUtil = {
  //由排序数组创建AVL树
  createAVLTree: function(array, low, high) {
   
    if (high < low) return null;

    var mid = Math.floor((low + high) / 2);

    var newNode = new AVLTreeNode(array[mid]);

    newNode.leftChild = this.createAVLTree(array, low, mid - 1);
    newNode.rightChild = this.createAVLTree(array, mid + 1, high);

    this.updateHeight(newNode);

    return newNode;
  },
  //前序遍历子树
  preOrderTraverse: function(node, visitFn) {
   
    if (node) {
      visitFn(node);

      this.preOrderTraverse(node.leftChild, visitFn);
      this.preOrderTraverse(node.rightChild, visitFn);
    }
  },
  //中序遍历子树
  inOrderTraverse: function(node, visitFn) {
   
    if (node) {
      this.inOrderTraverse(node.leftChild, visitFn);

      visitFn(node);

      this.inOrderTraverse(node.rightChild, visitFn);
    }
  },
  //插入节点并保持树平衡
  insertNodeWithBalance: function(node, key) {
   
    if (!node) {
      return new AVLTreeNode(key);
    }

    if (key < node.data) {
      node.leftChild = this.insertNodeWithBalance(node.leftChild, key);

      //平衡当前节点和左子树
      node = this.balanceLeft(node, key);
    } else {
      node.rightChild = this.insertNodeWithBalance(node.rightChild, key);

      //平衡当前节点和右子树
      node = this.balanceRight(node, key);
    }

    this.updateHeight(node);

    return node;
  },
  //移除子树中指定值的节点
  removeNodeWithBalance: function(node, key) {
   
    if (!node) return null;

    if (key < node.data) {
      node.leftChild = this.removeNodeWithBalance(node.leftChild, key);

      //平衡当前节点和左子树
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值