Balanced binary tree and its C + + implementation AVL

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;
} 
Published 12 original articles, won praise 6, visited 2840
Private letter follow

Posted on Tue, 14 Jan 2020 05:20:03 -0500 by thehippy