AVL Tree and Binary Tree
AVL Tree
AVL tree is a self-balancing binary
search tree in which each node maintains an extra information called as balance
factor whose value is either -1, 0 or +1
Balance Factor
Balance factor of a node in an AVL
tree is the difference between the height of the left subtree and that of right
subtree of that node.
Balance Factor = (Height of Left Subtree
- Height of Right Subtree) or (Height of Right Subtree - Height of Left
Subtree)
The self balancing property of an AVL
tree is maintained by the balance factor. The value of balance factor should
always be -1, 0 or +1.
An example of a balanced AVL tree is:


Operations on an AVL tree
Various operations that can be
performed on an AVL tree are:
Rotating the subtrees in an AVL Tree
In rotation operation, the positions
of the nodes of a subtree are interchanged.
There are two types of rotations:
Left Rotate
In left-rotation, the arrangement of
the nodes on the right is transformed into the arrangements on the left node.
Algorithm
1. Let the initial tree be:


2. If y has a left subtree, assign x as
the parent of the left subtree of y.


3. If the parent of x p is NULL,
make y as the root of the tree.
4. Else if x is the left child of p,
make y as the left child of p.
5. Else assign y as
the right child of p.


6. Make y as the parent of x.


Right Rotate
In left-rotation, the arrangement of
the nodes on the left is transformed into the arrangements on the right node.
1. Let the initial tree be:


2. If x has a right subtree, assign y as the parent
of the right subtree of x.


3. If the parent of y is NULL,
make x as the root of the tree.
4. Else if y is the right child of its parent p,
make x as the right child of p.
5. Else assign x as
the left child of p.


6. Make x as the parent of y.


Left-Right and Right-Left Rotate
In left-right rotation, the
arrangements are first shifted to the left and then to the right.
1. Do left rotation on x-y.


2. Do right rotation on y-z.


In left-right rotation, the
arrangements are first shifted to the right and then to the left.
1. Do right rotation on x-y.


2. Do left rotation on z-y.


Algorithm to insert a newNode
A newNode is
always inserted as a leaf node with balance factor equal to 0.
1. Let the initial tree be:

Let the node to be inserted be:


Let the node to be inserted be:

2. Go to the appropriate leaf node to insert a newNode using
the following recursive steps.
Compare newKey with rootKey of current tree.
Compare newKey with rootKey of current tree.
a. If newKey < rootKey, call insertion algorithm on left subtree of
current node until the leaf node is reached.
b. Else if newKey > rootKey, call insertion algorithm on the right subtree of
current node until the leaf node is reached.
c. Else, return leafNode.


3. Compare leafKey obtained from above steps with newKey:
a. If newKey < leafKey, make newNode as the leftChild of leafNode.
b. Else, make newNode as rightChild of leafNode.


4. Update balanceFactor of the nodes.


5. If the nodes are unbalanced, then rebalance the
node.
a. If balanceFactor > 1, it means the height of the left
subtree is greater than that of the right subtree. So, do right rotation or
left-right rotation
a. If newNodeKey < leftChildKey do right rotation.
b. Else, do left-right rotation.




b. If balanceFactor < -1, it means the height of the right
subtree is greater than that of the left subtree. So, do right rotation or
right-left rotation
a. If newNodeKey > rightChildKey do left rotation.
b. Else, do right-left rotation
6. The final tree is:


Algorithm to Delete a node
A node is always deleted as a leaf
node. After deleting a node, the balance factors of the nodes get changed. In
order to rebalance the balance factor, suitable rotations are performed.
1. Locate nodeToBeDeleted (recursion is used to find nodeToBeDeleted in
the code used below).


2. There are three cases for deleting a node:
a. If nodeToBeDeleted is the leaf node (ie. does not have any
child), then remove nodeToBeDeleted.
b. If nodeToBeDeleted has one child, then substitute the contents
of nodeToBeDeleted with that of child. Remove the child.
c. If nodeToBeDeleted has two children, find the inorder successor w of nodeToBeDeleted (ie.
node with minimum value of key in the right subtree).


a. Substitute the contents of nodeToBeDeleted with
that of w.


b. Remove the leaf node w.


3. Update balanceFactor of the nodes.


4. Rebalance the tree if balance factor of any of the
nodes is not equal to -1, 0 or 1.
a. If balanceFactor of currentNode > 1,
a. If balanceFactor of leftChild >= 0, do right rotation.


b. Else do left-right rotation.
b. If balanceFactor of currentNode < -1,
a. If balanceFactor of rightChild <= 0, do left rotation.
b. Else do right-left rotation.
5. The final tree is:


Binary Tree
A complete binary tree is a binary
tree in which all the levels are completely filled except possibly the lowest
one, which is filled from the left.
A complete binary tree is just like a
full binary tree, but with two major differences
1. All the leaf elements must lean towards the left.
2. The last leaf element might not have a right
sibling i.e. a complete binary tree doesn't have to be a full binary tree.
Complete Binary Tree
Full Binary Tree vs Complete Binary
Tree

Comparison between full binary tree
and complete binary tree

Comparison between full binary tree
and complete binary tree

Comparison between full binary tree
and complete binary tree

How a Complete Binary Tree is
Created?
1. Select the first element of the list to be the root
node. (no. of elements on level-I: 

2. Put the second element as a left child of the root
node and the third element as the right child. (no. of elements on level-II: 2)

3. Put the next two elements as children of the left
node of the second level. Again, put the next two elements as children of the
right node of the second level (no. of elements on level-III: 4) elements).
4. Keep repeating until you reach the last element.

#include <stdio.h>
#include <stdlib.h>
struct data
{
int x, height;
struct data *kiri;
struct data *kanan;
};
int max(int a, int b)
{
if(a < b) return b;
else return a;
}
int getHeight (struct data *root)
{
if(root==NULL) return 0;
return root->height;
}
int getBFactor (struct data *root)
{
if(root==NULL) return 0;
return getHeight(root->kiri) - getHeight(root->kanan);
}
struct data *kananRotate (struct data *y)
{
struct data *x = y->kiri;
struct data *B = x->kanan;
x->kanan = y;
y->kiri = B;
y->height = max(getHeight(y->kiri), getHeight(y->kanan)+1);
x->height = max(getHeight(x->kiri), getHeight(x->kanan)+1);
return x;
}
struct data *kiriRotate(struct data *x)
{
struct data *y = x->kanan;
struct data *B = y->kiri;
y->kiri = x;
x->kanan = B;
x->height = max(getHeight(x->kiri), getHeight(x->kanan)+1);
y->height = max(getHeight(y->kiri), getHeight(y->kanan)+1);
return y;
}
struct data *predecessor (struct data *root)
{
struct data *curr = root->kiri;
while(curr->kanan !=NULL)
curr = curr->kanan;
return curr;
}
struct data *successor (struct data *root)
{
struct data *curr = root->kanan;
while(curr->kiri !=NULL)
curr = curr->kiri;
return curr;
}
struct data *newNode (int x)
{
struct data *curr = (struct data*) malloc (sizeof(data));
curr->x = x;
curr->height = 1;
curr->kiri = NULL;
curr->kanan = NULL;
return curr;
}
struct data *insert (struct data *root, int x)
{
if(root == NULL) return newNode(x);
else if(x < root->x)
root->kiri = insert(root->kiri, x);
else
root->kanan = insert (root->kanan, x);
root->height = max(getHeight(root->kiri), getHeight(root->kanan))+1;
int bFactor = getBFactor(root);
if(bFactor > 1 && x < root->kiri->x)
return kananRotate(root);
if(bFactor <-1 && x > root->kanan->x)
return kiriRotate(root);
if(bFactor > 1 && x > root->kiri->x)
{
root->kiri = kiriRotate(root->kiri);
return kananRotate(root);
}
if(bFactor < -1 && x< root->kanan->x)
{
root->kanan = kananRotate(root->kanan);
return kiriRotate(root);
}
return root;
}
struct data *deleteValue (struct data *root, int x)
{
if(root == NULL) return NULL;
if(x < root->x)
root->kiri = deleteValue(root->kiri, x);
else if(x > root->x)
root->kanan = deleteValue(root->kanan, x);
else
{
if(root->kiri == NULL ||root->kanan == NULL)
{
struct data *temp = NULL;
if(root->kiri !=NULL)
temp = root->kiri;
else
temp = root->kanan;
if(temp == NULL)
{
temp = root;
root = NULL;
}
else
*root = *temp;
free(temp);
}
else
{
struct data *temp = predecessor(root);
root->x = temp->x;
}
}
if(root == NULL) return 0;
root->height = max(getHeight(root->kiri), getHeight(root->kanan))+1;
int bFactor = getBFactor(root);
if(bFactor > 1 && getBFactor(root->kiri)>=0)
return kananRotate(root);
if(bFactor <-1 && getBFactor(root->kanan)<=0)
return kiriRotate(root);
if(bFactor > 1 && getBFactor(root->kiri)<0)
{
root->kiri = kiriRotate(root->kiri);
return kananRotate(root);
}
if(bFactor < -1 && getBFactor(root->kanan)>0)
{
root->kanan = kananRotate(root->kanan);
return kiriRotate(root);
}
return root;
}
void printAll(struct data *root)
{
if(root==NULL) return;
printAll(root->kiri);
printf(" %d ", root->x);
printAll(root->kanan);
}
struct data *freeAll(struct data *root)
{
if(root ==NULL) return NULL;
root->kiri = freeAll(root->kiri);
root->kanan = freeAll(root->kanan);
free(root);
return NULL;
}
int main()
{
struct data *root = NULL;
root = insert(root,5);
root = insert(root,6);
root = insert(root,7);
root = insert(root,0);
root = insert(root,4);
root = insert(root,3);
root = insert(root,8);
printAll(root);
puts("");
root = deleteValue(root, 3);
root = deleteValue(root, 4);
root = deleteValue(root, 8);
printAll(root);
root = freeAll(root);
getchar();
return 0;
}
Comments
Post a Comment