[C++] AVL tree (balanced binary tree)

1. Definition of AVL tree

AVL tree, full name balanced binary search (sorting) tree .

Although the binary search tree can shorten the search efficiency, if the data is ordered or close to the order, the binary search tree will degenerate into a single branch tree, and searching for elements is equivalent to searching for elements in the sequence table, which is inefficient . Therefore, two Russian mathematicians GMAdelson-Velskii and EM Landis invented a method to solve the above problem in 1962: when a new node is inserted into the binary search tree, if the left and right subtrees of each node can be guaranteed If the absolute value of the height difference does not exceed 1 (the nodes in the tree need to be adjusted), the height of the tree can be reduced, thereby reducing the average search length.

Balance Factor (Balance Factor, abbreviated as bf)
balance factor (bf): the depth of the left subtree of the node minus the depth of the right subtree. It can also be the depth of the right subtree minus the depth of the left subtree. It depends on individual implementation.

That is: the balance factor of the node = the height of the left subtree - the height of the right subtree.
Or the balance factor of the node = the height of the right subtree - the height of the left subtree.

AVL tree is essentially a binary search tree, but it has the following characteristics:

  • Its left and right subtrees are both AVL trees
  • The absolute value of the difference between the heights of the left and right subtrees (referred to as the balance factor) does not exceed 1 (-1/0/1)

This is an AVL tree
insert image description here

Second, the role of the AVL tree

There is a binary tree with n nodes. If it is a binary search tree with various shapes and may form a single branch tree with a height of n, then the worst time complexity of finding elements in this search tree O(n), the best time complexity is O( log 2 n log_2 nlog2n ).
If he is an AVL tree, his height is stable aslog 2 n log_2 nlog2n , the time complexity of finding elements is O(log 2 n log_2 nlog2n ). insert image description here
As can be seen from the above figure, the height of the tree is also different due to the different insertion methods for the same node. Especially in the case of a large number of inserted nodes and a positive order, the height of the binary tree will be O(N), but this will not happen with the AVL tree. The height of the tree is always O(lgN). Height The smaller , the smaller the time complexity of some basic operations on the tree. This is why we introduced the AVL tree.

Third, the insertion operation of the AVL tree

INSERT - UPDATE OF BALANCE FACTOR

When inserting an element, it will inevitably cause changes in the balance factor, so we need to update the balance factor at the same time when inserting. When the balance factor is greater than 1 or less than -1, we need to rotate and adjust to make The balance factor is normal again, thus ensuring that this binary tree is always an AVL tree.

Calculate using balance factor: right subtree height - left subtree height

Situation 1:
insert image description here
After inserting an element, the balance factor of the parent node needs to be updated. To insert an element in the left subtree of the parent node, the balance factor of the parent node is -1. To insert an element in the left subtree of the parent node, the balance factor of the parent node is + 1. If the balance factor of the parent node becomes 1 or -1 after updating, it needs to be updated upwards to the root node , because 1 or -1 means that the height of the node has changed and needs to be updated upwards.

Case 2:
insert image description here
After inserting an element, it is necessary to update the balance factor of the parent node, inserting an element in the left subtree of the parent node, the balance factor of the parent node is -1, inserting an element in the left subtree of the parent node, the balance factor of the parent node + 1. If the balance factor of the parent node becomes 0 after updating, there is no need to continue to update upwards , because changing to 0 can only indicate that the height of the tree has not changed, but it has become balanced relative to the original.

If the balance factor is not in the range of (-1/0/1) after updating the balance factor, a rotation operation is required. The following explains how to perform the rotation operation

Since there are many cases where insertion needs to be rotated, it can be roughly divided into four categories

Insertion - left single rotation

Animation presentation
Please add a picture description

Case 1
When the right subtree is high, elements are inserted on the right side of the right subtree, and left single rotation is required at this timeHere is the quote

Insertion - right single rotation

Animation presentation
Please add a picture description

Case 2:
When the left subtree is higher, elements are inserted on the left side of the left subtree, and right single rotation is required at this timeHere is the quote

Insertion - left and right double rotation

Case 3: When the left subtree is higher, insert elements on the right side of the left subtree. At this time, left and right double rotation is required, that is, first perform left single rotation on 30, and then perform right single rotation on 90Here is the quote

Insert - right left double rotation

Situation 4. When the right subtree is higher, insert elements on the left side of the right subtree. At this time, right and left double rotation is required, that is, first perform right single rotation on 90, and then perform left single rotation on 30
insert image description here

4. Verification of ALVL tree

int _Height(Node* root)
{
    
    
	//用来计算二叉树的高度
	if (root == NULL)
		return 0;
	int leftH = _Height(root->_left);
	int rightH = _Height(root->_right);
 
	return leftH > rightH ? leftH + 1 : rightH + 1;
}
 
bool _IsBalance(Node* root)
{
    
    
	if (root == NULL)
		return true;
	int leftH = _Height(root->_left);
	int rightH = _Height(root->_right);
 	
 	//检查平衡因子
	if (rightH - leftH != root->_bf)
	{
    
    
		cout << root->_kv.first << "节点平衡因子异常" << endl;
		return false;
	}
 	//通过计算左右子树的高度差判断这颗二叉树是否为AVL树
	return abs(leftH - rightH) < 2
		&& _IsBalance(root->_left)
		&& _IsBalance(root->_right);
		//检查高度差要检查二叉树中所有节点的左右子树的高度差
}
 
bool IsBalance()
{
    
    
	return _IsBalance(_root);
}

Five, AVL tree performance

The AVL tree is an absolutely balanced binary search tree, which requires that the absolute value of the height difference between the left and right subtrees of each node does not exceed 1, which can ensure efficient time complexity during query, that is, log 2 n log_2 nlog2n

However, if you want to do some structural modification operations on the AVL tree, the performance is very low . For example: when inserting, it must maintain its absolute balance, and the number of rotations is relatively large. What is worse is that when deleting, it is possible to keep the rotation until the root. s position. Therefore: if you need an efficient and ordered data structure for querying, and the number of data is static (that is, it will not change), you can consider an AVL tree, but a structure that is frequently modified is not suitable.

Guess you like

Origin blog.csdn.net/Tianzhenchuan/article/details/132353993
Recommended