(1) Definition of binary search tree
Compared with the non-self-balancing binary search tree, the AVL tree is a binary search tree with balanced conditions. This equilibrium condition must be maintained. For an AVL tree, the height difference between the left and right subtrees of each node is at most 1. Here, we define the height of the empty tree as -1. So one problem is that inserting a node can break the properties of the AVL tree, so we can do it with a correction to the tree, which we call rotation.
(3) Rotation of AVL tree
Since any node has at most two children, when the height is unbalanced, the height difference between the two subtrees at point a is 2. It is easy to see that this imbalance is likely to occur in the following four situations.
1. Perform an insertion into the left subtree of the left child of a.
2. Perform an insertion into the right subtree of the left son of a.
3. Perform an insertion into the left subtree of the right child of a.
4. Perform an insertion into the right subtree of the right child of a.
The first is the case where the insertion occurs outside (ie, the left-left case or the right-right case), which can be adjusted with a single rotation of the tree. The second is what happens internally. (i.e. left-right case or right-left case), which can be done with a single double spin.
(4) The operation routine of AVL tree.
1. Statement
#include <stdio.h> #include <stdlib.h> #ifndef _AVLTREE_H #define _AVLTREE_H #define DATA_TYPE int struct AvlNode; typedef struct AvlNode *Position; typedef struct AvlNode *Tree; Tree Delete_tree(Tree T); //Delete tree Tree New_tree(DATA_TYPE X); //Create a new tree Position Find(Tree T, DATA_TYPE X); //查找 Position Find_Min(Tree T); //find the minimum value of the tree Position Find_Max(Tree T); //find the maximum value of the tree Position Insert(Tree T, DATA_TYPE X); //Insert node Position Delete(Tree T, DATA_TYPE X); // Position Print_tree(Tree T); //Preorder traversal of binary tree static int Height(Position P); //Calculate the height of the current node static Position Single_Rotate_left(Position K2); //Single left-left rotation static Position Single_Rotate_right(Position K2); //Single rotation right to right static Position Double_Rotate_left(Position K3); //Double rotation left and right static Position Double_Rotate_right(Position K3); //Double rotation right and left static int Max(int a, int b); static Position Fix(Position K2); struct AvlNode { DATA_TYPE num; Tree left; Tree right; int height; }; #endif
2. The height of the node and the function of determining the maximum value
Tree Delete_tree(Tree T) { if (T != NULL) { Delete_tree(T->left); Delete_tree(T->right); free(T); } return NULL; } static int Height(Position P) { if (P == NULL) //height is -1 if the tree is empty return -1; else return P->height; }
3. Create a new search tree and delete a search tree
Tree New_tree(DATA_TYPE X) { Position first; first = malloc(sizeof(struct AvlNode)); if (first == NULL) return NULL; first->num = X; first->right = NULL; first->left = NULL; return first; } Tree Delete_tree(Tree T) { if (T != NULL) { Delete_tree(T->left); Delete_tree(T->right); free(T); } return NULL; }
4. Find the target node, find the minimum node and find the maximum node
Position Find(Tree T, DATA_TYPE X) { while (T != NULL) { if (X < T->num) T = T->left; else if (X > T->num) T = T->left; else return T; } return NULL; } Position Find_Min(Tree T) { if (T != NULL) { for (; T->left != NULL; T = T->left); return T; } return T; } Position Find_Max(Tree T) { if (T != NULL) { for (; T->left != NULL; T = T->right); return T; } return NULL; }
5. Insert a node
Position Insert(Tree T, DATA_TYPE X) { if (T == NULL) //Successfully find the insertion position { T = malloc(sizeof(struct AvlNode)); if (T == NULL) return NULL; else { T->num = X; T->height = 0; T->left = T->right = NULL; } } else if (X < T->num) //If the node to be inserted is smaller than the node, move to the left subtree { T->left = Insert(T->left, X); if (Height(T->left) - Height(T->right) == 2)//The difference between the height of the left subtree and the height of the right subtree is 2 if (X < T->left->num) //Determine whether the situation belongs to LL or LR T = Single_Rotate_left(T); else T = Double_Rotate_left(T); } else if (X > T->num) //If the node to be inserted is greater than the node, move to the right subtree { T->right = Insert(T->right, X); if (Height(T->right) - Height(T->left) == 2)//The difference between the height of the right subtree and the height of the left subtree is 2 if (X > T->right->num) //Determine whether the situation belongs to RR or RL T = Single_Rotate_right(T); else T = Double_Rotate_right(T); } T->height = Max(Height(T->left), Height(T->right)) + 1; //Update node height return T; }
6, delete the node
Position Delete(Tree T, DATA_TYPE X) { Position TmpCell; if (T == NULL) { printf("Element not found!!\n"); return NULL; } else if (T->num > X) //find element X to the left T->num = Delete(X, T->left); else if (T->num < X) //find element X to the right T->num = Delete(X, T->right); else if (T->left && T->right) //The element is found and the left and right subtrees are not empty { TmpCell = FindMin(T->right); //Replace the node to be deleted with the smallest node in the right subtree T->num = TmpCell->num; T->right = Delete(T->num, T->right); } else // element found and one of the left and right subtrees is empty { TmpCell = T; if (T->left == NULL) T = T->right; else if (T->right == NULL) T = T->left; free(TmpCell); } if (T != NULL) { T->height = Max(Height(T->left), Height(T->right)) + 1; //Update the height after deleting the node //Determine whether the balance is out of balance at node T if ((Height(T->left) - Height(T->right) >= 2) || (Height(T->right) - Height(T->left) >= 2)) { T = Fix(T); T->height = Max(Height(T->left), Height(T->right)) + 1; } } return T; }
static Position Fix(Position K2) { if (Height(K2->left) > Height(K2->right)) { //The height of the left son of the left son of K2 is greater than the height of the right son of the left son of K2, execute left single rotation, otherwise execute left-right double rotation if (Height(K2->left->left) > Height(K2->left->right)) K2 = Single_Rotate_Left(K2); else if (Height(K2->left->left) < Height(K2->left->right)) K2 = Double_Rotate_Left(K2); } else if (Height(K2->left) < Height(K2->right)) { //The height of the right son of the right son of K2 is greater than the height of the left son of the right son of K2, execute right single rotation, otherwise execute right-left double rotation if (Height(K2->right->right) > Height(K2->right->left)) K2 = Single_Rotate_Right(K2); else if (Height(K2->right->right) < Height(K2->right->left)) K2 = Double_Rotate_Right(K2); } return K2; }
7. Preorder print the nodes in the tree
Position Print_tree(Tree T) { if (T == NULL) { printf("The Tree is empty.\n"); return NULL; } else if (T->left != NULL && T->right != NULL) { printf("%d ", T->num); T->left = Print_tree(T->left); T->right = Print_tree(T->right); } else if (T->left != NULL && T->right == NULL) { printf("%d ", T->num); T->left = Print_tree(T->left); } else if (T->left == NULL && T->right != NULL) { printf("%d ", T->num); T->right = Print_tree(T->right); } else if (T->left == NULL && T->right == NULL) printf("%d ", T->num); return T; }
8. Rotation of the tree
Left-Left Single Rotation
static Position Single_Rotate_left(Position K2) { Position K1; K1 = K2->left; K2->left = K1->right; K1->right = K2; K2->height = Max(Height(K2->left), Height(K2->right)) + 1; K1->height = Max(Height(K1->left), K2->right) + 1; return K1; }
Right-to-right rotation
static Position Single_Rotate_right(Position K2) { Position K1; K1 = K2->right; K2->right = K1->left; K1->left = K2; K2->height = Max(Height(K2->right), Height(K2->left)) + 1; K1->height = Max(Height(K1->right), K2->height) + 1; return K1; }
Left and right double rotation
static Position Double_Rotate_left(Position K3) { K3->left = Single_Rotate_right(K3->left); return Single_Rotate_left(K3); }
Right and left double rotation
static Position Double_Rotate_right(Position K3) { K3->right = Single_Rotate_left(K3->right); return Single_Rotate_right(K3); }