【数据结构】AVL树

AVL树是一种高度平衡的二叉搜索树,保证任意节点的左右子树高度差不超过1。它提高了查找效率,但插入和删除可能导致不平衡,需要通过四种旋转(LL、LR、RL、RR)来恢复平衡。本文详细介绍了AVL树的性质、作用及Java实现。
摘要由CSDN通过智能技术生成

参考博客:https://blog.csdn.net/u012152619/article/details/84138633

定义:

通常高度平衡树用符号HB(k)表示,其中k为左子树和右子树的高度差,k叫做平衡因子
在HB(k)中,如果k = 1,那么这样的二叉搜索树叫做AVL树,即一棵AVL树是带有平衡条件的二叉搜索树;对于任意一个结点,左子树和右子树的高度差最多不能超过1。

1.AVL树的性质

一棵二叉树为AVL树,当且仅当满足如下条件:

  • 它是一棵二叉搜索树
  • 对任意结点X,其左子树的高度与其右子树的高度的差最多不超过1。

2.AVL树的作用

对于一般的二叉搜索树,其期望高度(即为一棵平衡树时)为log2n,其各操作的时间复杂度O(log2n)同时也由此而决定。但是,在某些极端的情况下(如在插入的序列是有序的时),二叉搜索树将退化成近似链或链,此时,其操作的时间复杂度将退化成线性的,即O(n)。我们可以通过随机化建立二叉搜索树来尽量的避免这种情况,但是在进行了多次的操作之后,由于在删除时,我们总是选择将待删除节点的后继代替它本身,这样就会造成总是右边的节点数目减少,以至于树向左偏沉。这同时也会造成树的平衡性受到破坏,提高它的操作的时间复杂度。

3. 旋转

如果在AVL树中进行插入或删除节点后,可能导致AVL树失去平衡。这种失去平衡的可以概括为4种姿态:LL(左左),LR(左右),RR(右右)和RL(右左)。下面给出它们的示意图:

在这里插入图片描述

上图中的4棵树都是"失去平衡的AVL树",从左往右的情况依次是:LL、LR、RL、RR。除了上面的情况之外,还有其它的失去平衡的AVL树,如下图:

在这里插入图片描述

上面的两张图都是为了便于理解,而列举的关于"失去平衡的AVL树"的例子。总的来说,AVL树失去平衡时的情况一定是LL、LR、RL、RR这4种之一,它们都有各自的定义:

(1)LL:LeftLeft,也称为"左左"。插入或删除一个节点后,根节点的左子树的左子树还有非空子节点,导致"根的左子树的高度"比"根的右子树的高度"大2,导致AVL树失去了平衡。
例如,在上面LL情况中,由于"根节点(8)的左子树(4)的左子树(2)还有非空子节点",而"根节点(8)的右子树(12)没有子节点";导致"根节点(8)的左子树(4)高度"比"根节点(8)的右子树(12)“高2。
(2)LR:LeftRight,也称为"左右”。插入或删除一个节点后,根节点的左子树的右子树还有非空子节点,导致"根的左子树的高度"比"根的右子树的高度"大2,导致AVL树失去了平衡。
例如,在上面LR情况中,由于"根节点(8)的左子树(4)的左子树(6)还有非空子节点",而"根节点(8)的右子树(12)没有子节点";导致"根节点(8)的左子树(4)高度"比"根节点(8)的右子树(12)“高2。
(3)RL:RightLeft,称为"右左”。插入或删除一个节点后,根节点的右子树的左子树还有非空子节点,导致"根的右子树的高度"比"根的左子树的高度"大2,导致AVL树失去了平衡。
例如,在上面RL情况中,由于"根节点(8)的右子树(12)的左子树(10)还有非空子节点",而"根节点(8)的左子树(4)没有子节点";导致"根节点(8)的右子树(12)高度"比"根节点(8)的左子树(4)“高2。
(4) RR:RightRight,称为"右右”。插入或删除一个节点后,根节点的右子树的右子树还有非空子节点,导致"根的右子树的高度"比"根的左子树的高度"大2,导致AVL树失去了平衡。
例如,在上面RR情况中,由于"根节点(8)的右子树(12)的右子树(14)还有非空子节点",而"根节点(8)的左子树(4)没有子节点";导致"根节点(8)的右子树(12)高度"比"根节点(8)的左子树(4)"高2。
如果在AVL树中进行插入或删除节点后,可能导致AVL树失去平衡。AVL失去平衡之后,可以通过旋转使其恢复平衡,下面分别介绍"LL(左左),LR(左右),RR(右右)和RL(右左)"这4种情况对应的旋转方法。

4.Java版本实现

package tree;

public class AVLTree<T> {
   
	class Node<T>{
   
		private Node<T>  left = null;
		private Node<T>  right = null;
		private T data;
		private int hight;
		
		public Node(T d) {
   
			data = d;
			hight = 1;
		}

		public Node<T> getLeft() {
   
			return left;
		}

		public void setLeft(Node<T>  left) {
   
			this.left = left;
		}

		public Node<T>  getRight() {
   
			return right;
		}

		public void setRight(Node<T>  right) {
   
			this.right = right;
		}

		public T getData() {
   
			return data;
		}

		public void setData(T data) {
   
			this.data = data;
		}

		public int getHight() {
   
			return hight;
		}

		public void setHight(int hight) {
   
			this.hight = hight;
		}
	}
	private Node<T> root;
	
	public AVLTree(T value) {
   
		root = new Node<T>(value);
	
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值