Data Structure: Self-Balancing Binary Search Tree (AVL Tree)

(1) Definition of binary search tree

In computer science, a binary tree is a tree structure with at most two subtrees per node. Usually subtrees are called "left subtree" and "right subtree". Binary trees are often used to implement binary search trees and binary heaps.
Each node of a binary tree has at most two subtrees (there is no node with a degree greater than 2). The subtrees of a binary tree are divided into left and right, and the order cannot be reversed. The root of each subtree is called the son of the root r, and r is the parent of the root of each subtree.
Every binary tree with N nodes will require N+1 NULL pointers. For each node X in the tree, all the key values ​​in its left subtree are less than the key value of X, and all the key values ​​in its right subtree are greater than the key value of X.
The average depth of a binary search tree is O(log N).
(2) AVL tree and non-self-balancing 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);
}





Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325988884&siteId=291194637