AVL树

一.AVL树的概念
一棵AVL树或者是空树,或者是具有以下性质的二叉搜索树

  • 左右子树都是AVL树
  • 左右子树高度之差(平衡因子)的绝对值不超过1
    例如:
    在这里插入图片描述
    上面这棵树不是一个AVL树,因为节点16的平衡因子为2,超过了1,此时为了让它变成AVL树,则要进行旋转

2.AVL树节点的定义

template<class K,class V>
struct AVLTreeNode
{
   AVLTreeNode<K,V>* _left;      //左孩子节点
   AVLTreeNode<K,V>* _right;      //右孩子节点  
   AVLTreeNode<K,V>* _parent;    //双亲节点
   int _bf;                     //平衡因子
   std::pair<K,V> _kv;
   
   AVLTreeNode(const std::pair<K,V>& kv)
               :_left=nullptr    
               ,_right=nullptr
               ,_parent=nullptr
               ,_bf(0)
               ,_kv(kv)
    {}
 }          

3.AVL树的插入

  • 首先按照二叉搜索树的方法找到新节点的插入位置(如果元素不存在则插入,存在则返回false)
  • 新节点插入后,AVL树的平衡可能会被破坏,所以此时要进行更新平衡因子(如果新节点插在双亲结点的左侧,则双亲结点的平衡因子–,否则平衡因子++)
  • 如果双亲节点的平衡因子变为1或-1,则证明原来的平衡因子为0,此时子树有一侧高度增加,因此要继续向上进行更新平衡因子知道平衡因子为0
  • 如果双亲节点的平衡因子变为2或-2,则证明该树已经不满足AVL树性质,因此要进行旋转(具体方法在下一篇)

4.AVL树的插入实现

bool Insert(const std::pair<K, V>& kv)
	{
		if (_root == nullptr)            //如果树为空,则直接插入新节点
		{
			_root = new Node(kv);
			_root->_bf = 0;
			return true;
		}
		Node* parent = nullptr;
		Node* cur = _root;
		while (cur)
		{
			if (cur->_kv.first > kv.first)               //如果新节点k值小于cur,则向左子树继续查找
			{
				parent = cur;
				cur = cur->_left;
			}
			else if (cur->_kv.first<kv.first)            //如果新节点k值大于cur,则向右子树继续查找
			{
				parent = cur;
				cur = cur->_right;
			}
			else              //新节点已经存在,不再插入
			{
				return false;
			}
		}
		//找到插入位置进行插入
		cur = new Node(kv);          
		if (parent->_kv.first>kv.first)    
		{
			parent->_left = cur;
			cur->_parent = parent;
		}
		else
		{
			parent->_right = cur;
			cur->_parent = parent;
		}

		//更新平衡因子
		while (parent)
		{
			if (cur == parent->_left)      //如果插入在左子树,则双亲的平衡因子-1
			{
				parent->_bf--;
			}
			else                      //如果插入在右子树,则双亲的平衡因子+1
			{
				parent->_bf++;
			}
			if (parent->_bf == 0)
			{
				break;          //双亲的平衡因子为0,不再更新
			}
			else if (abs(parent->_bf) == 1)
			{
				//2.高度变了,继续更新
				cur = parent;
				parent = parent->_parent;
			}
			else if (abs(parent->_bf) == 2)
			{
				//不平衡旋转
				if (parent->_bf == 2)
				{
					if (cur->_bf == -1)
						RotateRL(parent);     //右左双旋
					else if (cur->_bf == 1)
						RotateL(parent);            //左单旋
				}
				else if (parent->_bf==-2)
				{
					if (cur->_bf == 1)
						RotateLR(parent);          //左右双旋
					else if (cur->_bf == -1)
						RotateR(parent);            //右单旋
				}  
				break;
			}
			else
			{
				assert(false);
			}
		}
		return true;
	}

5.AVL树的性能
AVL树是一棵绝对平衡的二叉搜索树,要求每个节点的左右子树高度差不超过1,可以保证查询时高效的时间复杂度,即log2(N);但是如果对结构进行修改操作,性能就会很低下。由于插入后也要维护平衡,则要通过大量旋转来维护。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值