##
title: balanced binary tree (AVL)

date: 2020-01-14 11:26:36

tags: data structure

#### 1.1 definition of balanced binary tree

In order to solve the problem that if the binary search tree is inserted in an inappropriate order, it will turn into a single chain (see the discussion in the article of binary search tree). For example, building a binary search tree according to the increasing sequence will lead to a one-sided situation, so that the binary tree can not play a role in keeping the efficiency of O (log n) search. Therefore, the balanced binary tree is derived by making the number of layers of binary tree smaller.

AVL is still a binary search tree (the name of AVL was proposed by two Soviet scientists G.M.Adekse-Velskil and E.M.Landis who discovered the tree), so it is also called AVL tree.

The difference between the height of left and right subtrees is called the equilibrium factor of this node

Because it is necessary to obtain the balance factor for each node, a height is added to the node of the tree to record the height of the subtree whose current node is the root node

struct node { int v, height; //v is the node weight height is the current subtree height node *lchild, *rchild; //Left and right child node address };

Write new node:

node* newNode(int v) { node* Node = new node; Node->v = v; //Node weight Node->height = 1; //Node height is initially 1 Node->lchild = Node->rchild = NULL; //No left or right children in initial state return Node; }

Obtain the current height of the subtree where the current node root of the subtree is located:

//Get the current height of the subtree with root as the root node int getHeight(node* root) { if(root == NULL) return 0; //Empty node height is 0 return root->height; }

Calculation of equilibrium factor:

//Equilibrium factor int getBalanceFactor(node* root) { //Left subtree height minus right subtree height return getHeight(root->lchild) - getHeight(root->rchild); }

Thinking: why not directly record the balance factor of nodes but record the height? Because there is no way to directly obtain the balance factor of the current subtree to calculate the balance factor of this node, it needs to be indirectly obtained by the height of the subtree. Obviously, the height of the subtree where the node root is located is equal to the greater value of the height of its left subtree and its right subtree + 1. Therefore, the height can be updated by the following functions:

void updateHeight(node* root) { //Max (left child height, right child height) + 1 root->height = max(getHeight(root->lchild), getHeight(root->rchild)) + 1; }

#### 2 basic operation of balanced binary tree

The basic operations of AVL include find, insert, build tree and delete. The deletion operation is complex, mainly introduces AVL search, insertion and establishment

##### 2.1 search operation

//Lookup operation void search(node* root, int x) { if(root == NULL) { //Empty tree lookup failed printf("search faild\n"); return; } if(x == root->data) { //Find successful access printf("%d\n", root->data); } else if(x < root->data) { search(root->lchild, x); } else { search(root->rchild, x); } }

##### 2.2 insertion operation

First, two basic operations are introduced, which are the basic operations of rotation to be done after the insertion operation determines which mode.

//left Rotation void L(node* &root) { node* temp = root->rchild; root->rchild = temp->lchild; temp->lchild = root; updataHeight(root); updataHeight(temp); root = temp; }

There's also a right turn

//Right rotation void R(node* &root) { node* temp = root->lchild; root->lchild = temp->rchild; temp->rchild = root; updateHeight(root); updateHeight(temp); root = temp; }

It can be seen that the left and right rotation are a pair of opposite processes.

If there is a balanced binary tree, after inserting a node, the absolute value of the balance factor of the node may be greater than 1. As long as the imbalance node closest to the inserted node is adjusted to normal, all nodes in the path will be balanced

Note that the balance factor is the height difference between the left subtree and the right subtree. The function to find the balance factor of the root point is written as BF(root)

Therefore, there is the following table:

Tree form | Adjustment method | |
---|---|---|

LL | BF(root) = 2, BF(root->lchild) = 1 | Right turn root |

LR | BF(root) = 2, BF(root->lchild) = -1 | First rotate root - > lchild left, then rotate root right |

RR | BF(root) = -2, BF(root->rchild) = -1 | Rotate root left |

RL | BF(root) = -2, BF(root->rchild) = 1 | First right turn root - > rchild, then left turn root |

For the implementation of the insertion code, the insertion code of AVL tree is based on the insertion code of binary search tree, and the balance operation is not considered. The code is as follows:

//Insert node with weight v void insert(node* &root, int v) { if(root == NULL) { //Arrive at empty node root = newNode(v); return; } if(v < roor->v) { //v is smaller than the weight of root node insert(root->lchild, v); } else { insert(root->rchild, v); } }

On this basis, it is necessary to judge the balance of the nodes from the bottom to the top, so the height of the subtree is updated after each insert function, and the balance operation is carried out according to the tree shape of LL, LR, RR and RL

//Insert node with weight v void insert(node* &root, int v) { if(root == NULL) { //Arrive at empty node root = newNode(v); return; } if(v < root->v) { //v is smaller than the weight of root node insert(root->lchild, v); //Insert to left subtree updateHeight(root); //Update tree height if(getBalanceFactor(root) == 2) { //Root imbalance if(getBalanceFactor(root->lchild) == 1) { //Type LL R(root); } else if(getBalanceFactor(root->lchild) == -1) { //Type LR L(root->lchild); R(root); } } } else { //v is larger than the weight of root node insert(root->rchild, v); //Insert right subtree updateHeight(root); //Update tree height if(getBalanceFactor(root) == -2) { if(getBalanceFactor(root->rchild) == -1) { //Type RR L(root); } else if(getBalanceFactor(root->rchild) == 1) { //Type RL R(root->rchild); L(root); } } } }

##### 3 Establishment of AVL tree

With the above foundation, the establishment of AVL tree is to insert nodes step by step. Adjust tree balance while inserting.

//The establishment of AVL tree node* Create(int data[], int n) { node* root = NULL; //New empty root for(int i = 0; i < n; i++) { insert(root, data[i]); //Insert data[0]~data[n-1] into AVL tree } return root; //Return to root }

#### 4 example:

An AVL tree is a self-balancing binary search tree. In an AVL tree, the heights of the two child subtrees of any node differ by at most one; if at any time they differ by more than one, rebalancing is done to restore this property. Now given a sequence of insertions, you are supposed to tell the root of the resulting AVL tree. Input Specification: Each input file contains one test case. For each case, the first line contains a positive integer N (≤20) which is the total number of keys to be inserted. Then N distinct integer keys are given in the next line. All the numbers in a line are separated by a space. Output Specification: For each test case, print the root of the resulting AVL tree in one line. Sample Input 1: 5 88 70 61 96 120 Sample Output 1: 70 Sample Input 2: 7 88 70 61 96 120 90 65 Sample Output 2: 88

Code

#include<cstdio> #include<algorithm> using namespace std; struct node { int v, height; //v is the node weight and height is the current subtree height node *lchild, *rchild; //Left and right child node address } *root; //Generate a new node, v is the node weight node* newNode(int v) { node* Node = new node; //Apply for the address space of a node variable Node->v = v; //Node weight is v Node->height = 1; //Initial height of node is 1 Node->lchild = Node->rchild = NULL; //There is no left or right child node in the initial state return Node; } int getHeight(node* root) { if(root == NULL) return 0; //Empty node height is 0 return root->height; } void updateHeight(node* root) { //Max (height of left child node, height of right child node) + 1 root->height = max(getHeight(root->lchild), getHeight(root->rchild)) + 1; } int getBalanceFactor(node* root) { //Subtracts the height of the right subtree from the height of the left subtree return getHeight(root->lchild) - getHeight(root->rchild); } //Left rotation void L(node* &root) { node* temp = root->rchild; root->rchild = temp->lchild; temp->lchild = root; updateHeight(root); //Update height of combination A updateHeight(temp); //Update the height of node B root = temp; } //Right rotation void R(node* &root) { node* temp = root->lchild; root->lchild = temp->rchild; temp->rchild = root; updateHeight(root); updateHeight(temp); root = temp; } //Insert node with weight v void insert(node* &root, int v) { if(root == NULL) { //Arrive at empty node root = newNode(v); return; } if(v < root->v) { //v is smaller than the weight of root node insert(root->lchild, v); //Insert to left subtree updateHeight(root); //Update tree height if(getBalanceFactor(root) == 2) { if(getBalanceFactor(root->lchild) == 1) { //Type LL R(root); } else if(getBalanceFactor(root->lchild) == -1) { //Type LR L(root->lchild); R(root); } } } else { //v is larger than the weight of root node insert(root->rchild, v); //Insert right subtree updateHeight(root); //Update tree height if(getBalanceFactor(root) == -2) { if(getBalanceFactor(root->rchild) == -1) { //Type RR L(root); } else if(getBalanceFactor(root->rchild) == 1) { //Type RL R(root->rchild); L(root); } } } } //node* Create(int data[], int n) { // node* root = NULL; / / create a new empty root node root // for(int i = 0; i < n; i++) { // insert(root, data[i]); / / insert data[0]~data[n-1] into AVL // } // return root; //} int main() { int n, v; scanf("%d", &n); for(int i = 0; i < n; i++) { scanf("%d", &v); insert(root, v); } printf("%d\n", root->v); return 0; }