Height Balanced Binary Search Tree
- The concept of AVL tree
- Implementation of AVL tree
-
- 1.Definition of AVL tree nodes
- 2.Insertion of AVL tree
- 3.Rotation of AVL tree
-
- 3.1 The new node is inserted into the right side of the higher right subtree --- right right: left single rotation
- 3.2 A new node is inserted to the left side of the higher left subtree --- left left: right single rotation
- 3.3 The new node is inserted into the right side of the higher left subtree --- left and right: first left single rotation and then right single rotation
- 3.4 A new node is inserted into the left side of the higher right subtree --- right left: first right single rotation and then left single rotation
- 4.Verification of AVL tree
- AVL tree implementation and verification of all codes
The concept of AVL tree
AVL tree ( Adelson-Velsky and Landis Tree ) is the earliest self-balancing binary search tree invented in computer science . In an AVL tree, the maximum height difference between two subtrees corresponding to any node is 1, so it is also called a height-balanced tree . Find, insert, and delete have average and worst-case time complexityO(logN)
. Adding and removing elements may require one or more tree rotations to rebalance the tree. The AVL tree is named after its inventors, GM Adelson-Velsky and Evgenii Landis , who disclosed this data structure in their 1962 paper " An algorithm for the organization of information ."
The balancing factor of a node is the height of its left subtree minus the height of its right subtree (and sometimes the opposite). Nodes with a balance factor of 1, 0 or -1 are considered balanced. Nodes with a balance factor of -2 or 2 are considered unbalanced and require the tree to be rebalanced. The balancing factor can be stored directly in each node, or calculated from the height of a subtree that may be stored in the node.
algorithm | average | worst |
---|---|---|
space | O(n) | O(n) |
search | O(log n) | O(log n) |
insert | O(log n) | O(log n) |
delete | O(log n) | O(log n) |
1. Operation
The basic operations of AVL trees generally involve operating the same algorithms that operate on unbalanced binary search trees. But do one or more so-called " AVL spins " before or subsequently.
The chart below represents four situations with four columns, and each row represents the action to be performed in that situation. In the case of left-right and right-right, only one rotation operation is required; in the case of left-right and right-left, two rotation operations are required.
The animation below demonstrates the situation when nodes are continuously inserted into the AVL tree, and demonstrates left rotation ( Left Rotation ), right rotation ( Right Rotation ), right-left rotation ( Right-Left Rotation ), left-right rotation ( Left-Right Rotation ), and subtrees. Right Rotation with children
2.Delete
Deletion from the AVL tree can be accomplished by rotating the node to be deleted downward into a leaf node, and then directly removing the leaf node. Because at most log n nodes are rotated during rotation into leaf nodes , and each AVL rotation takes a fixed time, the deletion process takes O(log n ) time overall .
3.Search
It can be performed like an ordinary binary search tree, so it takes O(log n ) time because the AVL tree is always balanced. No special preparation is required, and the structure of the tree is not changed by the search. (This is in contrast to a stretch tree search, which changes the tree structure as a result of the search.)
4. Implementation description
Assume that the balance factor is the value obtained by subtracting the height of the right subtree from the height of the left subtree. It is also assumed that the pointer of the root node of the smallest subtree that is unbalanced due to the insertion of a node in the binary sorting tree is a (that is, a is the distance from the tree). If the insertion point is the nearest ancestor node and the absolute value of the balance factor exceeds 1), the rules after losing balance can be summarized as the following four situations:
- One-way right-handed balancing processing LL : Since a node is inserted into the left subtree of the root node of the left subtree of *a, the balance factor of a increases from 1 to 2, causing the subtree with a as the root to lose balance, so it needs to be performed A right rotation operation;
- One-way left-handed balancing processing RR : Since a node is inserted into the right subtree of the root node of the right subtree of *a, the balance factor of a changes from -1 to -2, causing the subtree with a as the root to lose balance. Perform a left rotation operation;
- Bidirectional rotation (first left, then right) balance processing LR : Since a node is inserted into the right subtree of the root node of the left subtree of *a, the balance factor of a increases from 1 to 2, causing the subtree rooted with a to lose balance. , two rotations (first left and then right) are required.
- Bidirectional rotation (right first, then left) balancing processing RL : Since a node is inserted into the left subtree of the root node of the right subtree of *a, the balance factor of a changes from -1 to -2, resulting in the subtree with a as the root. If you lose your balance, you need to perform two rotations (first to the right and then to the left).
The recursive algorithm for inserting a new data element e on the balanced binary sorting tree AVL tree (Adelson-Velsky and Landis Tree) can be described as follows :
- If the AVL tree is an empty tree, insert a new node with the data element e as the root node of the AVL tree, and the depth of the tree increases by 1;
- If the key of e is equal to the key of the root node of the AVL tree, do not proceed;
- If the key of e is less than the key of the root node of the AVL tree, and there is no node with the same key as e in the left subtree of the AVL tree, then e is inserted into the left subtree of the AVL tree, and when When the depth of the left subtree after insertion increases (+1), the following different situations will be handled:
- The balance factor of the root node of the AVL tree is -1 (the depth of the right subtree is greater than the depth of the left subtree, then change the balance factor of the root node to 0, and the depth of BBST remains unchanged;
- The balance factor of the root node of the AVL tree is 0 (the depths of the left and right subtrees are equal): then change the balance factor of the root node to 1 and increase the depth of BBST by 1;
- The balance factor of the root node of the AVL tree is 1 (the depth of the left subtree is greater than the depth of the right subtree): Then if the balance factor of the root node of the left subtree of the AVL tree is 1: then one-way right-handed balancing processing is required. And after right-turn processing, the balance factor of the root node and the root node of its right subtree is changed to 0, and the depth of the tree remains unchanged;
- If the keyword of e is greater than the keyword of the root node of the AVL tree, and there is no node with the same keyword as e in the right subtree of the AVL tree, then e is inserted into the right subtree of the AVL tree, and when When the depth of the right subtree after insertion increases (+1), different situations are handled.
Implementation of AVL tree
1.Definition of AVL tree nodes
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;
AVLTreeNode(const pair<K, V>& kv)
:_left(nullptr)
, _right(nullptr)
, _parent(nullptr)
, _kv(kv)
, _bf(0)
{
}
};
This C++ template structure represents a node (AVLTreeNode) of an AVL tree. The AVL tree is a self-balancing binary search tree. This structure contains the following members:
_left
: Pointer to the left child node._right
: Pointer to the right child node._parent
: Pointer to parent node._kv
: A key-value pair used to store the node's keyword and associated value._bf
: Balance Factor (Balance Factor), used to represent the balance state of the node. Typically, the balancing factor is the height of the left subtree minus the height of the right subtree. AVL trees require the balance factor of each node to be in the range [-1, 1] to maintain the balance of the tree.
This structure represents a node in an AVL tree. Usually in an AVL tree implementation, you have a pointer to the root node to access the entire tree. The node structure of the AVL tree includes a balance factor _bf
to help maintain the balance of the tree. When a node is inserted or deleted, corresponding rotation operations need to be performed based on the balance factor to ensure the balance of the tree.
2.Insertion of AVL tree
Here we first define the structurestruct AVLTree
Contains the following members:
typedef AVLTreeNode<K, V> Node;
private:
Node* _root = nullptr;
Define insertion member function:
bool Insert(const pair<K, V>& kv)
{
if (_root == nullptr)
{
_root = new Node(kv);
return true;
}
Node* parent = nullptr;
Node* cur = _root;
while (cur)
{
if (cur->_kv.first < kv.first)
{
parent = cur;
cur = cur->_right;
}
else if (cur->_kv.first > kv.first)
{
parent = cur;
cur = cur->_left;
}
else
{
return false;
}
}
cur = new Node(kv);
if (parent->_kv.first < kv.first)
{
parent->_right = cur;
}
else
{
parent->_left = cur;
}
cur->_parent = parent;
// 控制平衡
while (parent)
{
if (cur == parent->_right)
{
parent->_bf++;
}
else
{
parent->_bf--;
}
if (parent->_bf == 0)
{
break;
}
else if (abs(parent->_bf) == 1)
{
parent = parent->_parent;
cur = cur->_parent;
}
else if (abs(parent->_bf) == 2)
{
// 说明parent所在子树已经不平衡了,需要旋转处理
if (parent->_bf == 2 && cur->_bf == 1)
{
RotateL(parent);
}
else if ((parent->_bf == -2 && cur->_bf == -1))
{
RotateR(parent);
}
else if (parent->_bf == -2 && cur->_bf == 1)
{
RotateLR(parent);
}
else if (parent->_bf == 2 && cur->_bf == -1)
{
RotateRL(parent);
}
else
{
assert(false);
}
break;
}
else
{
assert(false);
}
}
return true;
}
The main function of this code is to insert a new key-value pair into the AVL tree kv
and maintain the balance of the tree after insertion. Here are the main steps of the code:
- If the tree is empty (
_root == nullptr
), directly create a new root node_root
and insert itkv
, then return. - If the tree is not empty, enter the logic of inserting nodes:
- Use the
parent
andcur
pointers to traverse the tree to find where the insertion should occur. - If
cur
the key of the current node is lesskv
than the key of , move to the right subtree, otherwise move to the left subtree until an empty position is found to insert a new node.
- Use the
- After inserting a new node, the node's parent node pointer needs to be updated
_parent
. - Next is the logic to maintain the balance of the tree:
- During the insertion process, the balance factor of the parent node is updated upwards through a loop
_bf
. - If the balance factor of a node is 0, it means that the height of its subtree has not changed , and you can stop updating the balance factor, because the balance factor of the parent node will not change either.
- If the balance factor of a node is 1 or -1, it means that the height of its subtree has changed , and the balance factor needs to be updated upwards.
- If the balance factor of a node is 2 or -2, it means that the tree is unbalanced and needs to be rotated to restore balance.
- During the insertion process, the balance factor of the parent node is updated upwards through a loop
- The choice of rotation operation depends on the balancing factors of the unbalanced node and its child nodes. Generally, AVL trees have four rotation operations, namely left rotation ( RotateL ), right rotation ( RotateR ), left and right rotation ( RotateLR ) and right left rotation ( RotateRL ).
Update rules for balancing factors
- New additions are on the left,
parent->bf--
; New additions are on the right,parent->bf++
- After the update,
parent->bf==1 or -1
, it means that the balance factor of the parent before the insertion is 0, which means that the height of the left and right subtrees is equal. After the insertion, one side is higher and needs to continue to be updated.- After updating,
parent->bf==0
, it means that the balance factor before parent is inserted is1 or -1
, which means that one side of the left and right subtrees is high and the other is low. After the insertion, both sides are the same height. The short side is filled in by the insertion. The height of the subtree where the parent is located remains unchanged, and there is no need to continue going up. renew- After the update,
parent->bf==2 or -2
, it means that the balance factor before the parent is inserted is1 or -1
, the critical value has been balanced, and the insertion becomes2 or -2
, the subtree where the parent is located needs to be rotated.- After the update,
parent->bf>2 or <-2
, this condition is not true. If it exists, it means that there was a problem before the insertion and needs to be checked forward.
3.Rotation of AVL tree
If a new node is inserted into an originally balanced AVL tree, it may cause imbalance. At this time, the structure of the tree must be adjusted to make it balanced. Depending on the insertion position of the node, the rotation of the AVL tree is divided into four types:
3.1 The new node is inserted to the right of the higher right subtree - right-right: left single rotation
void RotateL(Node* parent)
{
Node* subR = parent->_right;
Node* subRL = subR->_left;
parent->_right = subRL;
if (subRL)
subRL->_parent = parent;
Node* ppNode = parent->_parent;
subR->_left = parent;
parent->_parent = subR;
if (_root == parent)
{
_root = subR;
subR->_parent = nullptr;
}
else
{
if (ppNode->_left == parent)
{
ppNode->_left = subR;
}
else
{
ppNode->_right = subR;
}
subR->_parent = ppNode;
}
subR->_bf = parent->_bf = 0;
}
- First, save the pointers
parent
to the right subtree of parent nodesubR
andsubR
the left subtree of .subRL
- Point
parent
the right subtree pointer of_right
,subRL
which willsubRL
be used as the newparent
right subtree of . - If
subRL
exists (not nullptr), thesubRL
parent node pointer of_parent
is pointed toparent
to ensure that the tree is connected correctly. - Get
parent
the pointer to the parent nodeppNode
of the to determine how to connectsubR
. - Point
subR
the left subtree pointer_left
ofparent
and pointparent
the parent node pointer of to complete the left rotation._parent
subR
- If
parent
is the root node (_root == parent
), you need to update the root node_root
assubR
and setsubR
the parent node pointer_parent
of to nullptr to ensure that the root of the tree is properly connected. - Otherwise, if
parent
is not the root node, connect to the correct location based on the position ofparent
in its parent node , and update the parent node pointer of .ppNode
subR
subR
_parent
ppNode
- Finally, set the balance factor of
parent
and to 0, since their heights are unchanged after the left rotation.subR
_bf
3.2 The new node is inserted to the left side of the higher left subtree - left-left: right single rotation
void RotateR(Node* parent)
{
Node* subL = parent->_left;
Node* subLR = subL->_right;
parent->_left = subLR;
if (subLR)
subLR->_parent = parent;
Node* ppNode = parent->_parent;
subL->_right = parent;
parent->_parent = subL;
if (_root == parent)
{
_root = subL;
subL->_parent = nullptr;
}
else
{
if (ppNode->_left == parent)
{
ppNode->_left = subL;
}
else
{
ppNode->_right = subL;
}
subL->_parent = ppNode;
}
subL->_bf = parent->_bf = 0;
}
- First, save pointers
parent
to the left subtree of the parent nodesubL
andsubL
the right subtree of .subLR
parent
Point the left subtree pointer_left
of to ,subLR
which willsubLR
be the newparent
left subtree of .- If
subLR
exists (not nullptr), thesubLR
parent node pointer of_parent
is pointed toparent
to ensure that the tree is connected correctly. - Get
parent
the pointer to the parent nodeppNode
of the to determine how to connectsubL
. - Point
subL
the right subtree pointer_right
ofparent
and pointparent
the parent node pointer of to complete the right rotation._parent
subL
- If
parent
is the root node (_root == parent
), you need to update the root node_root
assubL
and setsubL
the parent node pointer_parent
of to nullptr to ensure that the root of the tree is properly connected. - Otherwise, if
parent
is not the root node, connect to the correct location based on the position ofparent
in its parent node , and update the parent node pointer of .ppNode
subL
subL
_parent
ppNode
- Finally, set the balance factors of
parent
and to 0 since their heights do not change after right rotation.subL
_bf
The principle is the same as left-handed rotation
3.3 The new node is inserted to the right side of the higher left subtree - left and right: first left single rotation and then right single rotation
void RotateLR(Node* parent)
{
Node* subL = parent->_left;
Node* subLR = subL->_right;
int bf = subLR->_bf;
RotateL(parent->_left);
RotateR(parent);
subLR->_bf = 0;
if (bf == 1)//上图为例,新增节点在c下方
{
parent->_bf = 0;
subL->_bf = -1;
}
else if (bf == -1)//上图为例,新增节点在b下方
{
parent->_bf = 1;
subL->_bf = 0;
}
else if (bf == 0)//上图为例,无其他子树,60为新增节点的情况
{
parent->_bf = 0;
subL->_bf = 0;
}
else
{
assert(false);
}
}
- First, save pointers
parent
to the left subtree of the parent nodesubL
andsubL
the right subtree of , and the balance factor of .subLR
subLR
bf
- Perform a left rotation operation
parent
on the left subtreesubL
of to adjust the structure of the subtree. - Then,
parent
perform a right rotation operation on to makesubL
becomesparent
the right subtree of . - Set
subLR
the balance factor_bf
of to 0 because there is no change in its height after rotation. - Update the node's
subLR
balance factor according to different values of the balance factor of :bf
- If
bf
is 1, it means thatsubL
the height of the left subtree of is greater than the right subtree,parent
set the balance factor of to 0, andsubL
set the balance factor of to -1. - If
bf
is -1, it meanssubL
that the height of the right subtree is greater than the left subtree,parent
the balance factor of is set to 1,subL
and the balance factor of is set to 0. - If
bf
is 0, it meanssubL
that the left and right subtrees of are of equal height, and the balance factors of and areparent
bothsubL
set to 0.
- If
- If
bf
it is not 1, -1 or 0, it will triggerassert(false)
, indicating that an abnormal situation has occurred.
3.4 Insert a new node to the left side of the higher right subtree - right left: first rotate right and then rotate left
void RotateRL(Node* parent)
{
Node* subR = parent->_right;
Node* subRL = subR->_left;
int bf = subRL->_bf;
RotateR(parent->_right);
RotateL(parent);
subRL->_bf = 0;
if (bf == 1)
{
subR->_bf = 0;
parent->_bf = -1;
}
else if (bf == -1)
{
subR->_bf = 1;
parent->_bf = 0;
}
else if (bf == 0)
{
parent->_bf = 0;
subR->_bf = 0;
}
else
{
assert(false);
}
}
- First, save the pointers
parent
of the right subtree of the parent nodesubR
andsubR
the left subtree of , as well as the balance factor of .subRL
subRL
bf
- Perform a right rotation operation
parent
on the right subtreesubR
of to adjust the structure of the subtree. - Then,
parent
perform a left rotation operation on tosubR
becomeparent
the left subtree of . - Set
subRL
the balance factor_bf
of to 0 because there is no change in its height after rotation. - Update the node's
subRL
balance factor according to different values of the balance factor of :bf
- If
bf
is 1, it means thatsubRL
the height of the left subtree of is greater than the right subtree,subR
set the balance factor of to 0, andparent
set the balance factor of to -1. - If
bf
is -1, it meanssubRL
that the height of the right subtree is greater than the left subtree,subR
the balance factor of is set to 1,parent
and the balance factor of is set to 0. - If
bf
is 0, it meanssubRL
that the left and right subtrees of are of equal height, and the balance factors of and areparent
bothsubR
set to 0.
- If
- If
bf
it is not 1, -1 or 0, it will triggerassert(false)
, indicating that an abnormal situation has occurred.
The principle is the same as first turning left and then turning right
Summary :
If the subtree rooted at pParent is unbalanced, that is, the balance factor of pParent is 2 or -2, consider the following situations
- The balance factor of pParent is 2, indicating the height of the right subtree of pParent, and the root of the right subtree of pParent is pSubR
When pSubR's balance factor is 1, perform left single rotation
When pSubR's balance factor is -1, perform right-left double rotation
- The balance factor of pParent is -2, which means that the left subtree of pParent is high. Let the root of the left subtree of pParent be pSubL.
When the balance factor of pSubL is -1, a right single rotation is performed.
When the balance factor of pSubL is 1, a left or right double rotation is performed.
After the rotation is completed, the height of the subtree with the original pParent as the root is reduced, it is balanced, and there is no need to update it upwards.
4.Verification of AVL tree
4.1 Verify that it is a binary search tree
In-order traversal can obtain an ordered sequence, which is described as a binary search tree.
void InOrder()
{
_InOrder(_root);
cout << endl;
}
private:
void _InOrder(Node* root)
{
if (root == nullptr)
{
return;
}
_InOrder(root->_left);
cout << root->_kv.first << ":" << root->_kv.second << endl;
_InOrder(root->_right);
}
- First, check if the current node
root
is empty (ie the tree is empty). Returns if empty, ending the recursion. - Then, call the function recursively
_InOrder
to traverse the left subtreeroot->_left
. This will visit the nodes in the left subtree in ascending order. - Then, output the current node
root
's key and associated value, usuallycout
to the console using . - Finally, the function is called recursively again
_InOrder
to traverse the right subtreeroot->_right
. This will visit the nodes in the right subtree in ascending order.
4.2 Verify that it is a balanced tree
-
The absolute value of the height difference of each node subtree does not exceed 1 (note that if there is no balance factor in the node)
-
Whether the balance factor of the node is calculated correctly
height member functions
int Height(Node* root)
{
if (root == nullptr)
return 0;
return max(Height(root->_left), Height(root->_right)) + 1;
}
- First, check whether the current node
root
is empty (that is, whether the tree is empty). If it is empty, height 0 is returned, indicating that the height of the empty tree is 0. - If the current node
root
is not empty, then the function is called recursivelyHeight
to calculate the height of the left subtree and the height of the right subtree. - Use
max
the function to compare the height of the left subtree and the right subtree, and then add 1 (the height of the current node) to get the height of the entire tree. - Returns the height of the tree as the result of the function.
Balanced tree detection function
bool IsBalance()
{
return _IsBalance(_root);
}
private:
bool _IsBalance(Node* root)
{
if (root == nullptr)
{
return true;
}
int leftHT = Height(root->_left);
int rightHT = Height(root->_right);
int diff = rightHT - leftHT;
if (diff != root->_bf)
{
cout << root->_kv.first << "平衡因子异常" << endl;
return false;
}
return abs(diff) < 2
&& _IsBalance(root->_left)
&& _IsBalance(root->_right);
}
- First, check if the current node
root
is empty (ie the tree is empty). Returns if emptytrue
, since an empty tree is balanced. - If the current node
root
is not empty, then first calculate the height of the left subtree and the right subtree, and store them inleftHT
and respectivelyrightHT
. - Then, calculate the height difference between the left subtree and the right subtree (the height of the right subtree minus the height of the left subtree) and store it in
diff
the variable. _bf
Check whether the balance factor of the current node is equaldiff
. If not, it means that the balance factor is abnormal, and an error message will be output and returnedfalse
.- Continue to check whether the current node satisfies the balance condition of the AVL tree, that is, the absolute value of the balance factor does not exceed 1, and recursively check whether the left subtree and right subtree are also balanced (call the function)
_IsBalance
. - If all conditions are met, returns
true
indicates that the current subtree is balanced.
4.3 Verification use case
Regular scene 1
{
16, 3, 7, 11, 9, 26, 18, 14, 15}
Special scene 2
{
4, 2, 6, 1, 3, 5, 15, 7, 16, 14}
AVL tree implementation and verification of all codes
1.AVL code implementation
AVL.hpp
#pragma once
#include <iostream>
#include <algorithm>
#include <assert.h>
using namespace std;
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;
AVLTreeNode(const pair<K, V>& kv)
:_left(nullptr)
, _right(nullptr)
, _parent(nullptr)
, _kv(kv)
, _bf(0)
{
}
};
template<class K, class V>
struct AVLTree
{
typedef AVLTreeNode<K, V> Node;
public:
bool Insert(const pair<K, V>& kv)
{
if (_root == nullptr)
{
_root = new Node(kv);
return true;
}
Node* parent = nullptr;
Node* cur = _root;
while (cur)
{
if (cur->_kv.first < kv.first)
{
parent = cur;
cur = cur->_right;
}
else if (cur->_kv.first > kv.first)
{
parent = cur;
cur = cur->_left;
}
else
{
return false;
}
}
cur = new Node(kv);
if (parent->_kv.first < kv.first)
{
parent->_right = cur;
}
else
{
parent->_left = cur;
}
cur->_parent = parent;
while (parent)
{
if (cur == parent->_right)
{
parent->_bf++;
}
else
{
parent->_bf--;
}
if (parent->_bf == 0)
{
break;
}
else if (abs(parent->_bf) == 1)
{
parent = parent->_parent;
cur = cur->_parent;
}
else if (abs(parent->_bf) == 2)
{
if (parent->_bf == 2 && cur->_bf == 1)
{
RotateL(parent);
}
else if ((parent->_bf == -2 && cur->_bf == -1))
{
RotateR(parent);
}
else if (parent->_bf == -2 && cur->_bf == 1)
{
RotateLR(parent);
}
else if (parent->_bf == 2 && cur->_bf == -1)
{
RotateRL(parent);
}
else
{
assert(false);
}
break;
}
else
{
assert(false);
}
}
return true;
}
void InOrder()
{
_InOrder(_root);
cout << endl;
}
bool IsBalance()
{
return _IsBalance(_root);
}
private:
int BalanceFactor(Node* node)
{
if (node == nullptr)
{
return 0;
}
return Height(node->_left) - Height(node->_right);
}
bool _IsBalance(Node* root)
{
if (root == nullptr)
{
return true;
}
int leftHT = Height(root->_left);
int rightHT = Height(root->_right);
int diff = rightHT - leftHT;
if (diff != root->_bf)
{
cout << root->_kv.first << "平衡因子异常" << endl;
return false;
}
return abs(diff) < 2
&& _IsBalance(root->_left)
&& _IsBalance(root->_right);
}
int Height(Node* root)
{
if (root == nullptr)
return 0;
return max(Height(root->_left), Height(root->_right)) + 1;
}
void RotateL(Node* parent)
{
Node* subR = parent->_right;
Node* subRL = subR->_left;
parent->_right = subRL;
if (subRL)
subRL->_parent = parent;
Node* ppNode = parent->_parent;
subR->_left = parent;
parent->_parent = subR;
if (_root == parent)
{
_root = subR;
subR->_parent = nullptr;
}
else
{
if (ppNode->_left == parent)
{
ppNode->_left = subR;
}
else
{
ppNode->_right = subR;
}
subR->_parent = ppNode;
}
subR->_bf = parent->_bf = 0;
}
void RotateR(Node* parent)
{
Node* subL = parent->_left;
Node* subLR = subL->_right;
parent->_left = subLR;
if (subLR)
subLR->_parent = parent;
Node* ppNode = parent->_parent;
subL->_right = parent;
parent->_parent = subL;
if (_root == parent)
{
_root = subL;
subL->_parent = nullptr;
}
else
{
if (ppNode->_left == parent)
{
ppNode->_left = subL;
}
else
{
ppNode->_right = subL;
}
subL->_parent = ppNode;
}
subL->_bf = parent->_bf = 0;
}
void RotateLR(Node* parent)
{
Node* subL = parent->_left;
Node* subLR = subL->_right;
int bf = subLR->_bf;
RotateL(parent->_left);
RotateR(parent);
subLR->_bf = 0;
if (bf == 1)
{
parent->_bf = 0;
subL->_bf = -1;
}
else if (bf == -1)
{
parent->_bf = 1;
subL->_bf = 0;
}
else if (bf == 0)
{
parent->_bf = 0;
subL->_bf = 0;
}
else
{
assert(false);
}
}
void RotateRL(Node* parent)
{
Node* subR = parent->_right;
Node* subRL = subR->_left;
int bf = subRL->_bf;
RotateR(parent->_right);
RotateL(parent);
subRL->_bf = 0;
if (bf == 1)
{
subR->_bf = 0;
parent->_bf = -1;
}
else if (bf == -1)
{
subR->_bf = 1;
parent->_bf = 0;
}
else if (bf == 0)
{
parent->_bf = 0;
subR->_bf = 0;
}
else
{
assert(false);
}
}
void _InOrder(Node* root)
{
if (root == nullptr)
{
return;
}
_InOrder(root->_left);
cout << root->_kv.first << ":" << root->_kv.second << endl;
_InOrder(root->_right);
}
private:
Node* _root = nullptr;
};
2.AVL verification code implementation
AVLTEST.cpp
#include "AVL.hpp"
int main()
{
//int a[]={16, 3, 7, 11, 9, 26, 18, 14, 15};
int a[] = {
4, 2, 6, 1, 3, 5, 15, 7, 16, 14 };
AVLTree<int, int> avl1;
for (auto e : a)
avl1.Insert(make_pair(e, e));
avl1.InOrder();
cout << "IsBlance:" << avl1.IsBalance() << endl;
return 0;
}