文章目录
- AVL树
 - AVL树的概念
 - AVL树节点的定义
 - AVL树的插入
 - AVL树的旋转
 - 右单旋
 - 左单旋
 - 左右双旋
 - 右左双旋
 
- 代码实现
 
- 总结
 
AVL树
AVL树的概念
二叉搜索树在顺序有序或接近有序的情况下,而插入搜索树将退化为单叉树,此时查找的时间复杂度为O(n),效率低下。
 两位俄罗斯的数学家G.M.Adelson-Velskii和E.M.Landis在1962年发明了一种解决上述问题的方法:当向二叉搜索树中插入新节点后,保证每个节点的左右子树高度差的绝对值不超过1,即可降低树的高度,减少平均搜索长度。因此,AVL树也被叫做高度平衡二叉搜索树,插入,查找,删除在平均和最坏情况下的时间复杂度都是O( 
     
      
       
       
         l 
        
       
         o 
        
        
        
          g 
         
        
          2 
         
        
       
         n 
        
       
      
        log_2 n 
       
      
    log2n)。
AVL树节点的定义
	template<class K, class V>
	struct AVLTreeNode
	{
		AVLTreeNode<K, V>* _left;
		AVLTreeNode<K, V>* _right;
		AVLTreeNode<K, V>* _parent;
		pair<K, V> _kv;
		int _bf; //balance factor 平衡因子
		AVLTreeNode(const pair<K, V>& kv)
			:_left(nullptr)
			,_right(nullptr)
			,_parent(nullptr)
			,_kv(kv)
			,_bf(0)
		{}
	};
 
注意:实现AVL树平衡因子不是必须的,只不过有了平衡因子帮助我们更便捷地控制整棵树。
AVL树的插入
- 根据二叉搜索树的规则插入新节点
 
bool Insert(const pair<K, V> & kv)
		{
			root为空,特殊处理
			if (_root == nullptr)
			{
				_root = new Node(kv);
				return true;
			}
			Node* curr = _root;
			Node* parent = nullptr;
			while (curr)
			{
				if (curr->_kv.first < kv.first)
				{
					parent = curr;
					curr = curr->_right;
				}
				else if (curr->_kv.first > kv.first)
				{
					parent = curr;
					curr = curr->_left;
				}
				else
				{
					return false;
				}
			}
			将新节点和其父亲节点链接起来
			Node* newnode = new Node(kv);
			if (parent->_kv.first < kv.first)
				parent->_right = newnode;
			else
				parent->_left = newnode;
			newnode->_parent = parent;
			
			......
		}
 
- 不断向上更新平衡因子 
  
- 当前平衡因子为0,说明插入之前平衡因子为1 / -1,插入之后不改变树的高度,不会影响其他祖先节点,此时更新结束。
 - 当前平衡因子为1 / -1,说明插入之前平衡因子为0,插入之后当前节点地高度发生变化,会影响其他祖先节点,但是不违反规则,需要向上对祖先节点进行更新,直至当前节点为root。
 - 当前平衡因子为 2 / -2,此时当前节点所在地子树违反了平衡规则,需要进行处理–>旋转。
 
 
while (parent)
{
		if (parent->_left == newnode)
		{
			parent->_bf--;
		}
		else
		{
			parent->_bf++;
		}
		if (parent->_bf == 0)
			break;
		else if (parent->_bf == -1 || parent->_bf == 1)
		{
			newnode = parent;
			parent = parent->_parent;
		}
		else if (parent->_bf == -2 || parent->_bf == 2)
		{
			旋转处理
		}
		else
		{
			assert(false);
		}
}
 
AVL树的旋转
右单旋

void RotatoR(Node* parent)
{
	Node* subL = parent->_left;
	Node* subLR = subL->_right;
	parent->_left = subLR;
	if (subLR)
		subLR->_parent = parent;
	subL->_right = parent;
	Node* ppnode = parent->_parent;
	parent->_parent = subL;
	if (parent == _root)
	{
		_root = subL;
		subL->_parent = nullptr;
	}
	else
	{
		if (ppnode->_left == parent)
			ppnode->_left = subL;
		else
			ppnode->_right = subL;
		subL->_parent = ppnode;
	}
	parent->_bf = 0;
	subL->_bf = 0;
}
 
左单旋

void RotatoL(Node* parent)
{
	Node* subR = parent->_right;
	Node* subRL = subR->_left;
	parent->_right = subRL;
	if (subRL)
		subRL->_parent = parent;
	subR->_left = parent;
	Node* ppnode = parent->_parent;
	parent->_parent = subR;
	if (parent == _root)
	{
		_root = subR;
		subR->_parent = nullptr;
	}
	else
	{
		if (ppnode->_left == parent)
			ppnode->_left = subR;
		else
			ppnode->_right = subR;
		subR->_parent = ppnode;
	}
	parent->_bf = 0;
	subR->_bf = 0;
}
 
左右双旋

 旋转之前,45的平衡因子可能是-1/0/1,旋转完成之后,根据情况对其他节点的平衡因子进行调整
void RotatoLR(Node* parent)
{
	Node* subL = parent->_left;
	Node* subLR = subL->_right;
	int bf = subLR->_bf;
	RotatoL(subL);
	RotatoR(parent);
	subLR->_bf = 0;
	if (bf == 0)
	{
		subL->_bf = 0;
		parent->_bf = 0;
	}
	else if (bf == 1)
	{
		subL->_bf = -1;
		parent->_bf = 0;
	}
	else if (bf == -1)
	{
		subL->_bf = 0;
		parent->_bf = 1;
	}
}
 
右左双旋

void RotatoRL(Node* parent)
{
	Node* subR = parent->_right;
	Node* subRL = subR->_left;
	int bf = subRL->_bf;
	subRL->_bf = 0;
	RotatoR(subR);
	RotatoL(parent);
	if (bf == 0)
	{
		subR->_bf = 0;
		parent->_bf = 0;
	}
	else if (bf == 1)
	{
		subR->_bf = 0;
		parent->_bf = -1;
	}
	else if (bf == -1)
	{
		subR->_bf = 1;
		parent->_bf = 0;
	}
}
 
代码实现
namespace xxx
{
	template<class K, class V>
	struct AVLTreeNode
	{
		AVLTreeNode<K, V>* _left;
		AVLTreeNode<K, V>* _right;
		AVLTreeNode<K, V>* _parent;
		pair<K, V> _kv;
		int _bf; //balance factor 平衡因子
		AVLTreeNode(const pair<K, V>& kv)
			:_left(nullptr)
			,_right(nullptr)
			,_parent(nullptr)
			,_kv(kv)
			,_bf(0)
		{}
	};
	template<class K, class V>
	class AVLTree
	{
		typedef AVLTreeNode<K, V> Node;
	public:
		bool Insert(const pair<K, V> & kv)
		{
			if (_root == nullptr)
			{
				_root = new Node(kv);
				return true;
			}
			Node* curr = _root;
			Node* parent = nullptr;
			while (curr)
			{
				if (curr->_kv.first < kv.first)
				{
					parent = curr;
					curr = curr->_right;
				}
				else if (curr->_kv.first > kv.first)
				{
					parent = curr;
					curr = curr->_left;
				}
				else
				{
					return false;
				}
			}
			Node* newnode = new Node(kv);
			if (parent->_kv.first < kv.first)
				parent->_right = newnode;
			else
				parent->_left = newnode;
			newnode->_parent = parent;
			while (parent)
			{
				if (parent->_left == newnode)
				{
					parent->_bf--;
				}
				else
				{
					parent->_bf++;
				}
				if (parent->_bf == 0)
					break;
				else if (parent->_bf == -1 || parent->_bf == 1)
				{
					newnode = parent;
					parent = parent->_parent;
				}
				else if (parent->_bf == -2 || parent->_bf == 2)
				{
					if (parent->_bf == 2 && newnode->_bf == 1)
					{
						RotatoL(parent);
					}
					else if (parent->_bf == -2 && newnode->_bf == -1)
					{
						RotatoR(parent);
					}
					else if (parent->_bf == -2 && newnode->_bf == 1)
					{
						RotatoLR(parent);
					}
					else if (parent->_bf == 2 && newnode->_bf == -1)
					{
						RotatoRL(parent);
					}
					else
					{
						assert(false);
					}
					break;
				}
				else
				{
					assert(false);
				}
			}
			return true;
		}
		void RotatoL(Node* parent)
		{
			Node* subR = parent->_right;
			Node* subRL = subR->_left;
			parent->_right = subRL;
			if (subRL)
				subRL->_parent = parent;
			subR->_left = parent;
			Node* ppnode = parent->_parent;
			parent->_parent = subR;
			if (parent == _root)
			{
				_root = subR;
				subR->_parent = nullptr;
			}
			else
			{
				if (ppnode->_left == parent)
					ppnode->_left = subR;
				else
					ppnode->_right = subR;
				subR->_parent = ppnode;
			}
			parent->_bf = 0;
			subR->_bf = 0;
		}
		void RotatoR(Node* parent)
		{
			Node* subL = parent->_left;
			Node* subLR = subL->_right;
			parent->_left = subLR;
			if (subLR)
				subLR->_parent = parent;
			subL->_right = parent;
			Node* ppnode = parent->_parent;
			parent->_parent = subL;
			if (parent == _root)
			{
				_root = subL;
				subL->_parent = nullptr;
			}
			else
			{
				if (ppnode->_left == parent)
					ppnode->_left = subL;
				else
					ppnode->_right = subL;
				subL->_parent = ppnode;
			}
			parent->_bf = 0;
			subL->_bf = 0;
		}
		void RotatoLR(Node* parent)
		{
			Node* subL = parent->_left;
			Node* subLR = subL->_right;
			int bf = subLR->_bf;
			RotatoL(subL);
			RotatoR(parent);
			subLR->_bf = 0;
			if (bf == 0)
			{
				subL->_bf = 0;
				parent->_bf = 0;
			}
			else if (bf == 1)
			{
				subL->_bf = -1;
				parent->_bf = 0;
			}
			else if (bf == -1)
			{
				subL->_bf = 0;
				parent->_bf = 1;
			}
		}
		void RotatoRL(Node* parent)
		{
			Node* subR = parent->_right;
			Node* subRL = subR->_left;
			int bf = subRL->_bf;
			subRL->_bf = 0;
			RotatoR(subR);
			RotatoL(parent);
			if (bf == 0)
			{
				subR->_bf = 0;
				parent->_bf = 0;
			}
			else if (bf == 1)
			{
				subR->_bf = 0;
				parent->_bf = -1;
			}
			else if (bf == -1)
			{
				subR->_bf = 1;
				parent->_bf = 0;
			}
		}
		void InOrder()
		{
			_InOrder(_root);
			cout << endl;
		}
		bool IsAVLTree()
		{
			return _IsAVLTree(_root);
		}
	private:
		bool _IsAVLTree(Node* root)
		{
			if (root == nullptr)
				return true;
			int leftH = Height(root->_left);
			int rightH = Height(root->_right);
			return abs(leftH - rightH) <= 1
				&& _IsAVLTree(root->_left)
				&& _IsAVLTree(root->_right);
		}
		int Height(Node* node)
		{
			if (node == nullptr)
				return 0;
			int leftH = Height(node->_left);
			int rightH = Height(node->_right);
			return 1 + max(leftH, rightH);
		}
		void _InOrder(Node* root)
		{
			if (root == nullptr)
				return;
			_InOrder(root->_left);
			cout << root->_kv.second << ' ';
			_InOrder(root->_right);
		}
		Node* _root = nullptr;
	};
}
 
总结
AVL树是一棵绝对平衡的二叉搜索树,其要求每个节点的左右子树高度差的绝对值都不超过1,这样可以保证查询时高效的时间复杂度,即 l o g 2 ( N ) log_2 (N) log2(N)。但是如果要对AVL树做一些结构修改的操作,性能非常低下,比如:插入时要维护其绝对平衡,旋转的次数比较多。因此:如果需要一种查询高效且有序的数据结构,而且数据的个数为静态的(即不会改变),可以考虑AVL树,但一个结构经常修改,就不太适合。













![[NSSCTF 2nd] web复现](https://img-blog.csdnimg.cn/direct/02130d2cf4bc4ca086dbf09aa4c44630.png)





