login

AVL Tree

An AVL tree is a self-balancing binary search tree, and it is the first such data structure to be invented. In an AVL tree, the heights of the two child subtrees of any node differ by at most one; therefore, it is also said to be height-balanced. Lookup, insertion, and deletion all take O(log n) time in both the average and worst cases, where n is the number of nodes in the tree prior to the operation. Insertions and deletions may require the tree to be rebalanced by one or more tree rotations.

The AVL tree is named after its two inventors, G.M. Adelson-Velskii and E.M. Landis, who published it in their 1962 paper "An algorithm for the organization of information."

The balance factor of a node is the height of its right subtree minus the height of its left subtree and a node with balance factor 1, 0, or -1 is considered balanced. A node with any other balance factor is considered unbalanced and requires rebalancing the tree. The balance factor is either stored directly at each node or computed from the heights of the subtrees.

AVL trees are often compared with red-black trees because they support the same set of operations and because red-black trees also take O(log n) time for the basic operations. AVL trees perform better than red-black trees for lookup-intensive applications.The AVL tree balancing algorithm appears in many computer science curricula.
  
ALV Implemention File (5.5 KB)
ALV Implemention File
AVL Tree Header File (0.6 KB)
AVL Tree Header File
Macro for Fatal Error (156 B)
Macro for Fatal Error
Test Program for AVL Tree (0.8 KB)
Test Program for AVL Tree

typedef int ElementType;

#ifndef _AvlTree_H
#define _AvlTree_H

struct AvlNode;
typedef struct AvlNode *Position;
typedef struct AvlNode *AvlTree;

AvlTree MakeEmpty( AvlTree T );
Position Find( ElementType X, AvlTree T );
Position FindMin( AvlTree T );
Position FindMax( AvlTree T );
AvlTree Insert( ElementType X, AvlTree T );
AvlTree Delete( ElementType X, AvlTree T );
ElementType Retrieve( Position P );

#endif 
#include "avltree.h"
#include <stdlib.h>
#include "fatal.h"

struct AvlNode
{
	ElementType Element;
	AvlTree  Left;
	AvlTree  Right;
	int      Height;
};

AvlTree MakeEmpty( AvlTree T )
{
	if( T != NULL )
	{
		MakeEmpty( T->Left );
		MakeEmpty( T->Right );
		free( T );
	}
	return NULL;
}

Position Find( ElementType X, AvlTree T )
{
	if( T == NULL )
		return NULL;
	if( X < T->Element )
		return Find( X, T->Left );
	else
		if( X > T->Element )
			return Find( X, T->Right );
		else
			return T;
}

Position FindMin( AvlTree T )
{
	if( T == NULL )
		return NULL;
	else
		if( T->Left == NULL )
			return T;
		else
			return FindMin( T->Left );
}

Position FindMax( AvlTree T )
{
	if( T != NULL )
		while( T->Right != NULL )
			T = T->Right;

	return T;
}


static int Height( Position P )
{
	if( P == NULL )
		return -1;
	else
		return P->Height;
}


static int Max( int Lhs, int Rhs )
{
	return Lhs > Rhs ? Lhs : Rhs;
}


/* This function can be called only if K2 has a left child */
/* Perform a rotate between a node (K2) and its left child */
/* Update heights, then return new root */

static Position SingleRotateWithLeft( 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->Height ) + 1;

	return K1;  /* New root */
}


/* This function can be called only if K1 has a right child */
/* Perform a rotate between a node (K1) and its right child */
/* Update heights, then return new root */

static Position SingleRotateWithRight( Position K1 )
{
	Position K2;

	K2 = K1->Right;
	K1->Right = K2->Left;
	K2->Left = K1;

	K1->Height = Max( Height( K1->Left ), Height( K1->Right ) ) + 1;
	K2->Height = Max( Height( K2->Right ), K1->Height ) + 1;

	return K2;  /* New root */
}


/* This function can be called only if K3 has a left */
/* child and K3's left child has a right child */
/* Do the left-right double rotation */
/* Update heights, then return new root */

static Position DoubleRotateWithLeft( Position K3 )
{
	/* Rotate between K1 and K2 */
	K3->Left = SingleRotateWithRight( K3->Left );

	/* Rotate between K3 and K2 */
	return SingleRotateWithLeft( K3 );
}


/* This function can be called only if K1 has a right */
/* child and K1's right child has a left child */
/* Do the right-left double rotation */
/* Update heights, then return new root */

static Position DoubleRotateWithRight( Position K1 )
{
	/* Rotate between K3 and K2 */
	K1->Right = SingleRotateWithLeft( K1->Right );

	/* Rotate between K1 and K2 */
	return SingleRotateWithRight( K1 );
}



AvlTree Insert( ElementType X, AvlTree T )
{
	if( T == NULL )
	{
		/* Create and return a one-node tree */
		T = malloc( sizeof( struct AvlNode ) );
		if( T == NULL )
			FatalError( "Out of space!!!" );
		else
		{
			T->Element = X; T->Height = 0;
			T->Left = T->Right = NULL;
		}
	}
	else
		if( X < T->Element )
		{
			T->Left = Insert( X, T->Left );
			if( Height( T->Left ) - Height( T->Right ) == 2 )
				if( X < T->Left->Element )
					T = SingleRotateWithLeft( T );
				else
					T = DoubleRotateWithLeft( T );
		}
		else
			if( X > T->Element )
			{
				T->Right = Insert( X, T->Right );
				if( Height( T->Right ) - Height( T->Left ) == 2 )
					if( X > T->Right->Element )
						T = SingleRotateWithRight( T );
					else
						T = DoubleRotateWithRight( T );
			}
			/* Else X is in the tree already; we'll do nothing */

			T->Height = Max( Height( T->Left ), Height( T->Right ) ) + 1;
			return T;
}


AvlTree Delete( ElementType X, AvlTree T )
{
	printf( "Sorry; Delete is unimplemented; %d remains\n", X );
	return T;
}

ElementType Retrieve( Position P )
{
	return P->Element;
}
#include "avltree.h"
#include <stdio.h>

main()
{
	AvlTree T;
	Position P;
	int i;
	int j = 0;

	T = MakeEmpty( NULL );
	for( i = 0; i < 50; i++, j = ( j + 7 ) % 50 )
		T = Insert( j, T );
	for( i = 0; i < 50; i++ )
		if( ( P = Find( i, T ) ) == NULL || Retrieve( P ) != i )
			printf( "Error at %d\n", i );

	/* for( i = 0; i < 50; i += 2 )
	T = Delete( i, T );

	for( i = 1; i < 50; i += 2 )
	if( ( P = Find( i, T ) ) == NULL || Retrieve( P ) != i )
	printf( "Error at %d\n", i );
	for( i = 0; i < 50; i += 2 )
	if( ( P = Find( i, T ) ) != NULL )
	printf( "Error at %d\n", i );
	*/
	printf( "Min is %d, Max is %d\n", Retrieve( FindMin( T ) ),
		Retrieve( FindMax( T ) ) );

	return 0;
}