0% found this document useful (0 votes)
4 views141 pages

Unit IV

The document discusses the concept of symbol tables in compiler design, which store information about identifiers in programming languages. It explains the operations on symbol tables, including insertion, removal, searching, and retrieval, and introduces tree implementations for efficiency. Additionally, it covers the optimal binary search tree (OBST) and AVL trees, detailing their properties, operations, and the importance of maintaining balance for efficient search times.

Uploaded by

giteshspatil905
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
4 views141 pages

Unit IV

The document discusses the concept of symbol tables in compiler design, which store information about identifiers in programming languages. It explains the operations on symbol tables, including insertion, removal, searching, and retrieval, and introduces tree implementations for efficiency. Additionally, it covers the optimal binary search tree (OBST) and AVL trees, detailing their properties, operations, and the importance of maintaining balance for efficient search times.

Uploaded by

giteshspatil905
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 141

UNIT IV

Search Trees
Symbol Table

• In the world of computer science, compiler design is a complex field that bridges the
gap between human-readable programming languages and machine-executable
code.
• While compilers and assemblers are scanning a program, each identifier must be
examined to determine if it is a keyword.
• This information concerning the keywords in a programming language is stored in a
symbol table.
• The symbol table is a kind of a ‘keyed table’ which stores <key, information> pairs with
no additional logical structure.
• A symbol table in compiler design is like a dictionary or a lookup table that keeps track
of various pieces of information about identifiers (variables, functions, labels, etc.)
used in the source code.
The operations performed on symbol tables are the following:

1. Inserting the <key, information> pairs into the collection.

2. Removing the <key, information> pairs by specifying the key.

3. Searching for a particular key.

4. Retrieving the information associated with a key.


Consider the following C++ statement:

int limit;

• When a compiler processes this statement, it will identify that int is a keyword and limit

is an identifier.

• Compiler classifies them as a keyword and a user-defined identifier.

• For identifying int as a keyword, the compiler is provided with a table of keywords.

• For faster search through a list of keywords, the symbol table is used as an efficient

data structure.
Trees implementation of Symbol table -
• It is a more efficient method of organizing symbol tables. Each record now has
two link fields, LEFT and RIGHT.
Representation of Symbol Table

• There are two different techniques for implementing a keyed table, namely, the symbol table

and the tree table.

• Static Tree Tables –

• When symbols are known in advance and no insertion and deletion is allowed, such a

structure is called a static tree table.

• An example of this type of table is a reserved word table in a compiler.

• This table is searched once for every occurrence of an identifier in a program.

• If an identifier is not present in the reserved word table, then it is searched for in

another table.

• When we know the keys and their probable frequencies of being searched, we can

optimize the search time by building an optimal binary search tree (OBST).

• The keys have history associated with their use, which is referred to as their probability

of occurrence.
Dynamic Tree Tables –

• A dynamic tree table is used when symbols are not known in advance but are inserted

as they come and deleted if not required.

• Dynamic keyed tables are those that are built on the-fly.

• The keys have no history associated with their use.

• The dynamically built tree that is a balanced BST is the best choice.
OPTIMAL BINARY SEARCH TREE

• The optimal binary search tree (Optimal BST) is also known as a


weight-balanced search tree.
• It is a binary search tree that provides the shortest possible search time or
expected search time.
• An Optimal Binary Search Tree (OBST), is a binary search tree that minimizes
the expected search cost.
• In a binary search tree, the search cost is the number of comparisons required
to search for a given key.
• In an OBST, each node is assigned a weight that represents the probability of
the key being searched for.
• The sum of all the weights in the tree is 1.0.
• The expected search cost of a node is the sum of the product of its
depth and weight, and the expected search cost of its children.
• If we have keys: 15, 25, 35, then see how many BST can be
formed. We will use the formula given below:
• Cost of a tree can be defined as follows

• Here, the total number of nodes are n, and l(ai) is the length of the ith key, a.
• Here, we assume that all the keys are searched with equal probabilities.
• However, in reality, the keys are searched with different probabilities, and it
should be taken care of while constructing the tree so that the keys searched
more often should require less time as compared to those searched rarely.
• This can be achieved by placing the more frequently searched key nodes
closer to the root as compared to those that are searched rarely, to reduce
the total number of average searches.
• A node is said to be closer to the root when its path length is lesser than that
of the other nodes.
• Then, cost of a tree is computed with respect to its node’s probability of search
and path length. Hence,

where,

Wi = frequency or probability (also called as weight of the ith node)

Li = level of a particular node calculated from the root node treated from level 0
• In BST all nodes have some frequency.
• According to frequency BST has some cost.
• Our objective is find minimum cost of BST.
• Let’s take on small example
• Key:- 10,11,12 and Frequency:- 2,1,6
• For the BSTs , all the keys represent internal nodes.
• all successful searches will always end at an internal node.
• all squares denote external nodes, which are fictitious.
• all unsuccessful searches will end at some external node.
• If there are n keys, there are n + 1 external nodes.
• So all the keys that are not a part of a BST belong to one of (n + 1) equivalence
classes Ei for 0 ≤ i ≤n.
• Hence, the cost of a BST is given as follows:

• Equation defines the cost of a BST in terms of the probabilities of


successful and unsuccessful searches and the level of a node.
EXAMPLE - Given the keys = {while, do, if} and probabilities p(i) = q(i) = 1/7 for
all i. Compute the cost of all possible BSTs and find the OBST.

Solution We get five possible BSTs for the given keys


Let us compute the cost of each BST.

keys = {while, do, if}


Similarly cost of each subtree = 15/7
• Practically, we cannot use such an approach to find an OBST as we will need
to draw all possible BSTs and then find the cost of all BSTs.
• As the number of keys increases, the number of BSTs also increases.
• Dynamic programming approach can be used to construct an OBST by
considering the probabilities of both successful and unsuccessful searches for
the given set of keys.
• We construct an OBST step-by-step using the following three formulae:
• The dynamic programming approach can be used to construct an OBST
stepwise, where the principal of optimality should hold at each step.
• The steps to find OBST are as follows:
• The initial cost table of the dynamic programming algorithm for constructing
an OBST is shown in Fig

• The values needed for computing C[i][j] are shaded in Fig.


• They are the values in row i and to the left of column j, and the values in
column j and the rows below row i.
• This computation is shown in Table
Table shows this computation.
Table shows this computation.
//OBST operations public:
#include<iostream> obst(int m)
using namespace std; {
#define MAX 10 n=m;
int keys[MAX],p[MAX],q[MAX]; for(int i=0;i<=n;i++)
{
struct node for(int j=0;j<=n;j++)
{ {
int key; R[i][j]=0;
node *left,*right; C[i][j]=0;
}; W[i][j]=0;
}
class obst }
{ }
int n; node* construct(int,int);
int R[MAX][MAX],C[MAX][MAX],W[MAX][MAX]; void display(node* root);
int cost(int*,int*,int);
};
void obst::display(node* root)
{
if(root!=NULL)
{
cout<<root->key<<" ";
display(root->left);
display(root->right);
}
}

node* obst::construct(int i,int j)


{
node* p;

if(i==j)
p=NULL;
else
{
p=new node;
p->key=keys[R[i][j]];
p->left=construct(i,R[i][j]-1);
p->right=construct(R[i][j],j);
}

return p;
}
int obst::cost(int* p,int* q,int n)
{ for(int h=2;h<=n;h++)
//Constructing the weight matrix {
for(int i=0;i<=n;i++) for(int i=0;i<=n-h;i++)
{ {
W[i][i]=q[i]; int j=i+h;
int m=R[i][j-1];
for(int j=i+1;j<=n;j++) int min=C[i][m-1]+C[m][j];
{ for(int k=m+1;k<=R[i+1][j];k++)
W[i][j]=W[i][j-1]+p[j]+q[j]; {
} int x=C[i][k-1] + C[k][j];
} if(x<min)
//Constructing the cost matrix {
for(int i=0;i<=n;i++) m=k;
{ min=x;
}
C[i][i]=W[i][i]; }
} C[i][j]=W[i][j]+min;
R[i][j]=m;
for(int i=0;i<=n-1;i++) }
{ }
int j=i+1;
C[i][j]=C[i][i]+C[j][j]+W[i][j];
R[i][j]=j;
}
cout<<"\nThe weight matrix: ";
for(int i=0;i<=n;i++)
{
for(int j=0;j<=n;j++)
cout<<W[i][j]<<" ";

cout<<"\n";
}

cout<<"\nThe cost matrix: ";


for(int i=0;i<=n;i++)
{
for(int j=0;j<=n;j++)
cout<<C[i][j]<<" ";

cout<<"\n";
}

cout<<"The root matrix: ";


for(int i=0;i<=n;i++)
{
for(int j=0;j<=n;j++)
cout<<W[i][j]<<" ";

cout<<"\n";
}
return C[0][n];
}
int main()
{
int n;
cout<<"\nEnter the number of keys: ";
cin>>n;
obst obj(n);

for(int i=1;i<=n;i++)
{
cout<<"Keys["<<i<<"]:";
cin>>keys[i];
cout<<"p["<<i<<"]:";
cin>>p[i];
}
for(int i=0;i<=n;i++)
{
cout<<"q["<<i<<"]:";
cin>>q[i];
}

int c=obj.cost(p,q,n);
cout<<"\nMinimum cost: "<<c;
node* root=obj.construct(0,n);
cout<<"\nInorder traversal";
obj.display(root);
cout<<"\n";
return 0;
}
Height Balanced Tree- AVL tree

• An AVL tree is a BST where the heights of the left and right subtrees of the root
differ by utmost 1 and the left and right subtrees are again AVL trees.
• The formal definition is as follows:

• In an AVL tree with n nodes, the searches, insertions, and deletions can all be
achieved in time O(log n), even in the worst case.
• To keep the tree height-balanced, we have to find out the balance factor of each
node in the tree after every insertion or deletion.
Balance Factor

• In an AVL tree, the balance factor of a node is the height difference between

its left and right subtrees. It ensures the tree remains balanced, with a

balance factor of 0 indicating equilibrium.

• All nodes have balance factors within the range [-1, 1], indicating a balanced

AVL tree. Mathematically, the balance factor (BF) of a node N is given by:

bf = h l − h r
Example of AVL Tree
AVL Tree Rotation

• In AVL tree, after performing operations like insertion and deletion we need to

check the balance factor of every node in the tree.

• If every node satisfies the balance factor condition then we conclude the

operation otherwise we must make it balanced.

• Whenever the tree becomes imbalanced due to any operation we use rotation

operations to make the tree balanced.Rotation operations are used to make the

tree balanced.

• Rotation is the process of moving nodes either to left or to right to make the tree

balanced.
• There are four rotations and they are classified into two types.
Single Left Rotation (LL Rotation) -
• If a node in a tree becomes unbalanced due to the nodes of the right subtree,
then we left-rotate the parent node to balance the tree.
• Left rotation is performed on a right-skewed binary search tree.
• In LL Rotation, every node moves one position to left from the current position.
• To understand LL Rotation, let us consider the following insertion operation in
AVL Tree...
Single Right Rotation (RR Rotation)
• If a tree is not height-balanced due to the left subtree, we rotate it in the
rightward direction to balance it.
• Right rotation is performed from left-skewed binary search trees.
• In RR Rotation, every node moves one position to right from the current position.
• To understand RR Rotation, let us consider the following insertion operation in
AVL Tree...
Left Right Rotation (LR Rotation)
• The LR Rotation is a sequence of single left rotation followed by a single right
rotation.
• In LR Rotation, at first, every node moves one position to the left and one position
to right from the current position.
• To understand LR Rotation, let us consider the following insertion operation in
AVL Tree...
Right Left Rotation (RL Rotation)
• The RL Rotation is sequence of single right rotation followed by single left
rotation.
• In RL Rotation, at first every node moves one position to right and one position
to left from the current position.
• To understand RL Rotation, let us consider the following insertion operation in
AVL Tree...
Operations on an AVL Tree

The following operations are performed on AVL tree...

1. Search

2. Insertion

3. Deletion
Search Operation in AVL Tree -
In an AVL tree, the search operation is performed with O(log n) time complexity. The search
operation in the AVL tree is similar to the search operation in a Binary search tree. We
use the following steps to search an element in AVL tree...
Step 1 - Read the search element from the user.
Step 2 - Compare the search element with the value of root node in the tree.
Step 3 - If both are matched, then display "Given node is found!!!" and terminate the function
Step 4 - If both are not matched, then check whether search element is smaller or larger than
that node value.
Step 5 - If search element is smaller, then continue the search process in left subtree.
Step 6 - If search element is larger, then continue the search process in right subtree.
Step 7 - Repeat the same until we find the exact element or until the search element is
compared with the leaf node.
Step 8 - If we reach to the node having the value equal to the search value, then display
"Element is found" and terminate the function.
Step 9 - If we reach to the leaf node and if it is also not matched with the search element, then
display "Element is not found" and terminate the function.
Insertion Operation in AVL Tree -

In an AVL tree, the insertion operation is performed with O(log n) time complexity. In AVL

Tree, a new node is always inserted as a leaf node. The insertion operation is performed

as follows...

Step 1 - Insert the new element into the tree using Binary Search Tree insertion logic.

Step 2 - After insertion, check the Balance Factor of every node.

Step 3 - If the Balance Factor of every node is 0 or 1 or -1 then go for next operation.

Step 4 - If the Balance Factor of any node is other than 0 or 1 or -1 then that tree is said to

be imbalanced. In this case, perform suitable Rotation to make it balanced and go for next

operation.
Algorithm
• The following steps are involved in performing the insertion operation of an
AVL Tree −
Step 1 − Create a node
Step 2 − Check if the tree is empty
Step 3 − If the tree is empty, the new node created will become the
root node of the AVL Tree.
Step 4 − If the tree is not empty, we perform the Binary Search Tree
insertion operation and check the balancing factor of the node
in the tree.
Step 5 − Suppose the balancing factor exceeds ±1, we apply suitable
rotations on the said node and resume the insertion from Step 4.
Example: Construct an AVL Tree by inserting numbers from 1 to 8.
Deletion Operation in AVL Tree

• The deletion operation in AVL Tree is similar to deletion operation in BST.

• But after every deletion operation, we need to check with the Balance Factor

condition.

• If the tree is balanced after deletion go for next operation otherwise perform suitable

rotation to make the tree Balanced.

• We know that deletion of any node in any binary search tree is handled in three

different cases:

1. The node is a leaf node

2. The node is an internal node having one child

3. The node is an internal node having two child nodes


Consider the following tree:

Suppose we wish to delete 50.


On deleting 50, 60 will be replaced by
50 and 50 will be deleted as shown:

Now, the tree has become


unbalanced due to the nodes: 60, 42
and 32.

This is a left-skewed tree so will


perform right rotation to balance it.
Thus, after performing the right
rotation, the tree will become as
follows:
//C++ program to Implement AVL Tree // Class Declaration
class avlTree
#include<iostream>
{
#include<cstdio> public:

#include<sstream> int height(avl_node *);


int diff(avl_node *);
#include<algorithm>
avl_node *rr_rotation(avl_node *);
#define pow2(n) (1 << (n)) avl_node *ll_rotation(avl_node *);

using namespace std; avl_node *lr_rotation(avl_node *);


avl_node *rl_rotation(avl_node *);
//Node Declaration
avl_node* balance(avl_node *);
struct avl_node avl_node* insert(avl_node *, int );

{ avl_node *deleteAVL(avl_node *, int );


void display(avl_node *, int);
int data;
void inorder(avl_node *);
struct avl_node *left; avlTree()

struct avl_node *right; {


root = NULL;
}*root;
}
};
//Main Contains Menu
int main()
{
int choice, item,dval;
avlTree avl;
while (1)
{
cout<<"\n---------------------"<<endl;
cout<<"AVL Tree Implementation"<<endl;
cout<<"\n---------------------"<<endl;
cout<<"1.Insert Element into the tree"<<endl;
cout<<"2.Display Balanced AVL Tree"<<endl;
cout<<"3.Delete"<<endl;
cout<<"4.Exit"<<endl;
cout<<"Enter your Choice: ";
cin>>choice;
switch(choice)
{
case 1:
cout<<"Enter value to be inserted: ";
cin>>item;
root = avl.insert(root, item);
break; case 4:
case 2: exit(1);
if (root == NULL) break;
{ default:
cout<<"Tree is Empty"<<endl; cout<<"Wrong Choice"<<endl;
continue; }
} }
cout<<"Balanced AVL Tree:"<<endl; return 0;
avl.display(root, 1); }
break;
case 3:
cout<<"delete:"<<endl;
cout<<"Enter value to be deleted: ";
cin>>dval;
root = avl.deleteAVL(root,dval);
cout<<endl;
break;
// Height of AVL Tree
int avlTree::height(avl_node *temp)
{
int h = 0;
if (temp != NULL)
{
int l_height = height (temp->left);
int r_height = height (temp->right);
int max_height = max (l_height, r_height);
h = max_height + 1;
}
return h;
}
//Height Difference

int avlTree::diff(avl_node *temp)

int l_height = height (temp->left);

int r_height = height (temp->right);

int b_factor= l_height - r_height;

return b_factor;

}
// Right- Right Rotation
avl_node *avlTree::rr_rotation(avl_node *parent)
{
avl_node *temp;
temp = parent->left;
parent->left = temp->right;
temp->right = parent;
return temp;
}
// Left- Left Rotation
avl_node *avlTree::ll_rotation(avl_node *parent)
{
avl_node *temp;
temp = parent->right;
parent->right = temp->left;
temp->left = parent;
return temp;
}
// Left - Right Rotation
avl_node *avlTree::lr_rotation(avl_node *parent)
{
avl_node *temp;
temp = parent->left;
parent->left = ll_rotation (temp);
return rr_rotation (parent);
}

// Right- Left Rotation


avl_node *avlTree::rl_rotation(avl_node *parent)
{
avl_node *temp;
temp = parent->right;
parent->right = rr_rotation (temp);
return ll_rotation (parent);
}
//Balancing AVL Tree
avl_node *avlTree::balance(avl_node *temp)
{
int bal_factor = diff(temp);
if (bal_factor > 1)
{
if (diff (temp->left) > 0)
temp = rr_rotation (temp);
else
temp = lr_rotation (temp);
}
else if (bal_factor < -1)
{
if (diff (temp->right) > 0)
temp = rl_rotation (temp);
else
temp = ll_rotation (temp);
}
return temp;
}
//Insert Element into the tree
avl_node *avlTree::insert(avl_node *root, int value)
{
if (root == NULL)
{
root = new avl_node;
root->data = value;
root->left = NULL;
root->right = NULL;
return root;
}
else if (value < root->data)
{
root->left = insert(root->left, value);
root = balance (root);
}
else if (value >= root->data)
{
root->right = insert(root->right, value);
root = balance (root);
}
return root;
}
//Display AVL Tree
void avlTree::display(avl_node *ptr, int level)
{
int i;
if (ptr!=NULL)
{
display(ptr->right, level + 1);
printf("\n");
if (ptr == root)
cout<<"Root -> ";
for (i = 0; i < level && ptr != root; i++)
cout<<" ";
cout<<ptr->data;
display(ptr->left, level + 1);
}
}
//Inorder Traversal of AVL Tree
void avlTree::inorder(avl_node *tree)
{
if (tree == NULL)
return;
inorder (tree->left);
cout<<tree->data<<" ";
inorder (tree->right);
}
avl_node *avlTree::deleteAVL(avl_node *root, int dval)
{
avl_node *temp;
if (root != NULL)
{
if (dval < root->data)
{
root->left = deleteAVL(root->left, dval);
if (diff(root) == -2)
{
if (diff(root->right) <= 0)
{
cout << "\n RR rotation \n";
root = rr_rotation(root);
}
else
{
cout << "\n RL rotation \n";
root = rl_rotation(root);
}
}
}
else if (dval > root->data)
{
root->right = deleteAVL(root->right, dval);
if (diff(root) == 2)
{
if (diff(root->left) >= 0)
{
cout << "\n LL rotation \n";
root = ll_rotation(root);
}
else
{
cout << "\n LR rotation \n";
root = lr_rotation(root);
}
}
}
else
{
if (root->right == NULL)
return (root->left);
else
{
// find leftmost of right
temp = root->right;
while (temp->left != NULL)
temp = temp->left;
root->data = temp->data;
root->right = deleteAVL(root->right, temp->data);
if (diff(root) == 2)
{
if (diff(root->left) >= 0)
root = ll_rotation(root);
else
root = lr_rotation(root);
}
}
}
}
else
return NULL;
return root;
}
Examples on AVL Tree

1. Construct an AVL tree for the following data: 30, 31, 32, 23, 22, 28, 24, 29,

26, 27, 34, 36

2. Construct an AVL tree for the following data: STA, add, lda , mov , jmp, trim,

xchg, mVi, div, nop, in, jnz

3. Construction of AVL tree (a) Key = STA (b) Key = ADD (c) Key = LDA (d)

Key = MOV (e) Key = JMP (f) Key = TRIM

4. Construct an AVL tree for the set of keys = {50, 55, 60, 15, 10, 40, 20, 45,

30, 70, 80}


Applications of AVL Tree:

• It is used to index huge records in a database and also to efficiently search in

that.

• For all types of in-memory collections, including sets and dictionaries, AVL

Trees are used.

• Database applications, where insertions and deletions are less common but

frequent data lookups are necessary Software that needs optimized search.

• It is applied in corporate areas and storyline games.


Advantages of AVL Tree:

1. AVL trees can self-balance themselves.

2. It is surely not skewed.

3. It provides faster lookups than Red-Black Trees

4. Better searching time complexity compared to other trees like binary tree.

Disadvantages of AVL Tree:

1. It is difficult to implement.

2. It has high constant factors for some of the operations.

3. Less used compared to Red-Black trees.

4. Due to its rather strict balance, AVL trees provide complicated insertion and

removal operations as more rotations are performed.

5. Take more processing for balancing.


Red-Black Tree
• Red Black Tree is a Binary Search Tree in which every node is colored either RED or
BLACK.
• A red–black tree is a BST with one extra bit of storage per node: its colour, which can either
be red or black.
• The tree is balanced by constraining the way nodes can be coloured on any path from the
root to a leaf; red-black tree ensures that no such path is more than twice as long as any
other.
Red-Black Tree

In Red Black Tree, the color of a node is decided based on the properties of Red-Black Tree.

Every Red Black Tree has the following properties.

Properties of Red Black Tree

1. Red - Black Tree must be a Binary Search Tree.

2. The ROOT node must be colored BLACK.

3. The children of Red colored node must be colored BLACK. (There should not be two

consecutive RED nodes).There are no two adjacent red nodes (A red node cannot

have a red parent or red child)

4. Every simple path from root to descendant leaf node contains same number of black

nodes.

5. Every new node must be inserted with RED color.

6. All the external nodes (leaf nodes) must be colored BLACK.


Insertion into RED BLACK Tree

While inserting a new node, the new node is always inserted as RED node. After

insertion of a new node, if the tree is violating the properties of the red-black tree

then, we do the following operations:-

1. Recolor

2. Rotation

To understand the insertion operation, let us understand the keys required to

define the following nodes:

1. Let u be the newly inserted node.

2. p is the parent node of u.

3. g is the grandparent node of u.

4. Un is the uncle node of u.


Insertion into RED BLACK Tree

Case -1

• The imbalancing is concerned with the color of grandparent child i.e., Uncle Node.

• If uncle node is red then four cases arises, and by doing recoloring imbalancing

can be removed.

• Left Right imbalance:

• In this, Red-Black Tree violates its property in such a manner that parent and

inserted child will be in red color at a position of left and right with respect to

grandparent.

• Therefore, it is termed as LEFT RIGHT imbalance.


Insertion into RED BLACK Tree

Removal of LRr imbalance can be done by:


i. Changing the color of node p from red to black.
ii. Changing the color of node Un from red to black.
iii. Changing the color of node g from black to red, if g is not a root node.
Note: If given g is root node then there will be no changes in color of g.
Insertion into RED BLACK Tree
2. Left Left imbalance:
• In this, Red-Black Tree violates its property in such a manner that parent
and inserted child will be in red color at a position of left and left with
respect to grandparent.
• Therefore, it is termed as LEFT LEFT imbalance.
Insertion into RED BLACK Tree
Removal of LLr imbalance can be done by:
i. Changing the color of node p from red to black.
ii. Changing the color of node Un from red to black.
iii. Changing the color of node g from black to red, if g is not a root node.
Note: If given g is root node then there will be no changes in color of g.
Insertion into RED BLACK Tree
3. Right Right imbalance:
• In this, Red-Black Tree violates its property in such a manner that parent
and inserted child will be in red color at a position of right and right with
respect to grandparent.
• Therefore, it is termed as RIGHT RIGHT imbalance.
Insertion into RED BLACK Tree

Removal of RRr imbalance can be done by:


i. Changing the color of node p from red to black.
ii. Changing the color of node Un from red to black.
iii. Changing the color of node g from black to red, if g is not a root node.
Note: If given g is root node then there will be no changes in color of g.
Insertion into RED BLACK Tree
4. Right Left imbalance:
• In this, Red-Black Tree violates its property in such a manner that parent and
inserted child will be in red color at a position of right and left with respect to
grandparent.
• Therefore, it is termed as RIGHT LEFT imbalance.
Insertion into RED BLACK Tree

Removal of RRr imbalance can be done by:


i. Changing the color of node p from red to black.
ii. Changing the color of node Un from red to black.
iii. Changing the color of node g from black to red, if g is not a root node.
Note: If given g is root node then there will be no changes in color of g.
Insertion into RED BLACK Tree
Case - 2

• The imbalancing can also be occurred when the child of grandparent i.e., uncle

node is black.

• Then also four cases will arise and in these cases imbalancing can be removed

by using rotation technique.

1. LR imbalancing

2. LL imbalancing

3. RR imbalancing

4. RL imbalancing
Insertion into RED BLACK Tree

LL and RR imbalancing can be removed by following two steps —


i. Apply single rotation of p about g.
ii. Recolor p to black and g to red.
Insertion into RED BLACK Tree
Insertion into RED BLACK Tree

LR and RL imbalancing can be removed by following two steps —

i. Apply double rotation of u about p followed by u about g.

ii. For LR/RL imbalancing, recolor u to black and recolor p and g to red.
Insertion into RED BLACK Tree
Steps for Insertion:
Insert the Node: Insert the new node like in a binary search tree. New nodes are always
inserted as red nodes.
ROOT Node: If new node is root, change color of new node as BLACK.
Check for Violations: After insertion, check for Red-Black Tree property violations and fix them
using Recoloring or Rotations followed by Recoloring.
Recoloring: If a parent and uncle are red then
a) Change color of parent and uncle as BLACK.
b) color of grand parent as RED if not ROOT.
c) repeat steps a and b till we reach the ROOT.
Rotations followed by Recoloring: If the parent is red but the uncle is black then, perform
rotations. There are four cases:
a) Left-Left (LL) Case and swap the colors of grand parent and parent.
b) Left-Right (LR) Case and swap the colors of grand parent and new node.
c) Right-Right (RR) Case and swap the colors of grand parent and parent.
d) Right-Left (RL) Case and swap the colors of grand parent and new node.
Algorithm for Insertion Operations ofRed Black Tree

RB-INSERT(T, k)
BST-INSERT(T, k) //normal BST insertion
while k.parent.color == RED
if k.parent == k.parent.parent.right
u = k.parent.parent.left //uncle
if u.color == RED
u.color = BLACK
k.parent.color = BLACK
k.parent.parent.color = RED
k = k.parent.parent
else if k == k.parent.left
k = k.parent
LEFT-ROTATE(T, k)
k.parent.color = BLACK
k.parent.parent.color = RED
RIGHT-ROTATE(T, k.parent.parent)
else (same as then clause with “left” and “right” exchanged)
T.root.color = BLACK
Example
Deletion Operation on RED BLACK Tree

• Deletion in a red-black tree is a bit more complicated than insertion.


• When a node is to be deleted, it can either have no children, one child or two children.
• Here are the steps involved in deleting a node in a red-black tree:
1. If the node to be deleted has no children, simply remove it and update the parent
node.
2. If the node to be deleted has only one child, replace the node with its child.
3. If the node to be deleted has two children, then replace the node with its in-order
successor, which is the leftmost node in the right subtree. Then delete the in-order
successor node as if it has at most one child.
4. After the node is deleted, the red-black properties might be violated. To restore these
properties, some color changes and rotations are performed on the nodes in the
tree. The changes are similar to those performed during insertion, but with different
conditions.
5. The deletion operation in a red-black tree takes O(log n) time on average, making it
a good choice for searching and deleting elements in large data sets.
Cases -
• Let v be the node to be deleted and u be the child that replaces v (Note that u is
NULL when v is a leaf and color of NULL is considered as black)
• Simple Case: If either u or v is red, we mark the replaced child as black
(No change in black height). Both u and v cannot be red as v is parent of u
and two consecutive reds are not allowed in red-black tree.
2. If both u and v are black -
1. Color u as double black. Now our task reduces to convert this double black to single
black. Note that If v is a leaf, then u is NULL and color of NULL is considered as black.
So the deletion of a black leaf also causes a double black.
2. Do following while the current node u is double black and it is not root. Let sibling of
node be s. If sibling s is black and at least one of sibling’s children is red (let it be r),
perform rotations(s). (already discussed under Insertion)
1. Left Left Case: s is left child of its parent and r is left child of s or both children of
s are red.
2. Left Right Case: s is left child of its parent and r is right child
3. Right Right Case: s is right child of its parent and r is right child of s or both
children of s are red.
4. Right Left Case: s is right child of its parent and r is left child of s.
3. If sibling is black and its both children are black, perform recoloring, and recur for the
parent if parent is black.
In this case, if parent was red, then we didn’t need to recur for parent, we can simply make
it black (red + double black = single black)
Deletion cases
A red-black tree should still remain a red-black tree after an element (key) is deleted.
Deletion Operations of Red Black Tree
Deletion operations in a Red-Black Tree (RBT) can be quite complex due to the
balancing rules that need to be maintained. In delete operation, we check color
of sibling to decide the appropriate case. In delete, the main violated property is,
in each path the same number of black nodes.
Steps for Deletion:

1. Find the Node: Like in a regular binary search tree, find the node that needs to
be deleted.

2. Perform Standard BST Delete:


Case 1: If node to be deleted is red (leaf node), then delete it.
• If node to be deleted is black (leaf node) replace with null & DB(Double Black)

Case-2: if root is DB, just remove DB


Case-3: if DB sibling is black & its both children's are black
• Remove DB
• Change the color of sibling to red
• Change the color of parent to
• black if read
• Double Black if black
• If still DB exit, then apply these cases.
Case-4 : if DB sibling is red.
• Swap colour of parent and its siblings
• Rotate parent in DB direction.
• Re-apply cases.
Case-5: if DB sibling is black, one of its Sibling's child is Red
•Swap colour of parent & sibling.

•Rotate parent in DB direction.


•Remove DB.
•Change colour of Sibling's red child to black.
Algorithm for Deletion Operations of Red Black Tree
RB-DELETE(T, x)
BST-DELETE(T, x)
while x ≠ T.root and x.color == BLACK
if x == x.parent.left
s = x.parent.right
if s.color == RED
s.color = BLACK
x.parent.color = RED
LEFT-ROTATE(T, x.parent)
s = x.parent.right
if s.left.color == BLACK and s.right.color == BLACK
s.color = RED
x = x.parent
else if s.right.color == BLACK
s.left.color = BLACK
s.color = RED
RIGHT-ROTATE(T, s)
s = x.parent.right
s.color = x.parent.right
x.parent.color = BLACK
s.right.color = BLACK
LEFT-ROTATE(T, x.parent)
x = T.root
else (same as then close with “right” and “left” exchanged)
x.color = BLACK
Example - Delete 30 from the RB tree
Example : Delete 15 from RB tree
Example : Delete ‘15’
Example : Delete ‘15’

(a) Swap DB’s parent’s color with DB’s


sibling’s color.
(b) Perform rotation at parent node in
direction of DB.
(c) Check which case can be applied in
the current tree.
(d) Apply case 3 as explained and the RB
tree is free from the DB node
Example : Delete ‘1’

Perform the basic preliminary steps- delete


the node with value 1 and replace it with
DB NIL node as shown in fig. Check for the
cases which fit the current tree and it’s
case 3(DB’s sibling is black).
Apply case 3 as discussed above and
you get the tree as shown in fig.

Node 5 has now become a double


black node. We need to get rid of it.

Search for cases that can be applied


and case 5 seems to fit here (not case
3).
Case 5 is applied as follows-

(a) swap colors of nodes 30 and 25 fig.

(b) Rotate at sibling node in the direction opposite to the DB node. Hence, perform right

rotation at node 30 and the tree becomes like fig.

The double black node still haunts the tree! Re-check the case that can be applied to this

tree and we find that case 6 (don’t fall for case 3) seems to fit.
Apply case 6 as follow-

(a) Swap colors of DB’s parent with DB’s sibling.

(b) Perform rotation at DB’s parent node in the direction of DB fig


(c) Change DB node to black node. Also, change the color of DB’s sibling’s
far-red child to black and the final RB tree will look fig
AA tree
• An AA tree is an alternative to red black trees.
• An AA tree is a balanced BST with the following properties:
1. Every node is colored either red or black.
2. The root is black.
3. If a node is red, both of its children are black.
4. Every path from a node to a null reference has the same number of black nodes.
5. Left children may not be red.
6. Unlike in red-black trees, red nodes on an AA tree can only be added as a right
sub-child i.e. no red node can be a left sub-child. The tree below is an AA tree.
Representing Balance Information in AA Tree

1. The level of every leaf node is one.


2. If a node is red, its level is the level of its parent.
3. If a node is black, its level is one less than the level of its parent.
4. The level of every left child is exactly one less than that of its parent.
5. The level of every right child is equal to or one less than that of its parent.
6. The level of every right grand child is strictly less than that of its
grandparent.
7. Every node of level greater than one, has two children.
Horizontal Link
• A link where the child's level is equal to that of its parent is called a horizontal link.
• Horizontal links are always right links.
• Red nodes are simply nodes that are located at the same level as their parents.
• For the AA tree shown above, the image below should help you understand which
nodes are red and which are black and which are the horizontal links.
Advantages of AA Trees -

• AA trees are more advantageous as they simplify the algorithms. The following

list explains the advantages:

• They eliminate half the reconstructing cases.

• They simplify deletion by removing an annoying case.

• If an internal node has only one child, that child must be a red child.

• We can always replace a node with the smallest child in the right subtree; it

will either be a leaf node or have a red child.

• An AA tree, which is a balanced BST, supports efficient operations, since most

operations only have to traverse one or two root-to-leaf paths.


K-dimensional tree
• A K-Dimensional Tree (also known as K-D Tree) is a space-partitioning data structure for organizing
points in a K-Dimensional space.
• This data structure acts similar to a binary search tree with each node representing data in the multi
dimensional space.
• The kd tree is a modification to the BST that allows for efficient processing of multi-dimensional search
keys.
• The purpose of the tree was to store spatial data with the goal of accomplishing:
• Nearest neighbor search.
• Range queries.
• Fast look-up.
How it works

• A simple example to showcase the insertion into a K-Dimensional Tree, we will use a k = 2.
• The points we will be adding are: (7,8), (12,3), (14,1), (4,12), (9,1), (2,7), and (10,19).
• We can see that the depth is
equivalent to 3, which is also
Log2(n) of the current K-D
Tree.
• On a plotted 2 dimensional graph the following K-D Tree will be the equivalent to:

• The points we will be adding are: (7,8),


(12,3), (14,1), (4,12), (9,1), (2,7), and
(10,19).
• Consider following points in a 2-D plane: (3, 6), (17, 15), (13, 15), (6, 12), (9, 1), (2, 7), (10, 19)

1. Insert (3, 6): Since tree is empty, make it the root node.
2. Insert (17, 15): Compare it with root node point. Since root
node is X-aligned, the X-coordinate value will be compared to
determine if it lies in the right subtree or in the left subtree.
This point will be Y-aligned.
3. Insert (13, 15): X-value of this point is greater than X-value of
point in root node. So, this will lie in the right subtree of (3, 6).
Again Compare Y-value of this point with the Y-value of point
(17, 15) (Why?). Since, they are equal, this point will lie in the
right subtree of (17, 15). This point will be X-aligned.
4. Insert (6, 12): X-value of this point is greater than X-value of
point in root node. So, this will lie in the right subtree of (3, 6).
Again Compare Y-value of this point with the Y-value of point
(17, 15) (Why?). Since, 12 < 15, this point will lie in the left
subtree of (17, 15). This point will be X-aligned.
5. Insert (9, 1):Similarly, this point will lie in the right of (6, 12).
6. Insert (2, 7):Similarly, this point will lie in the left of (3, 6).
7. Insert (10, 19): Similarly, this point will lie in the left of (13,
15).
How is space partitioned?
Y axis
1. Point (3, 6) will divide the space into two parts: Draw line X =
3.
2. Point (2, 7) will divide the space to the left of line X = 3 into
two parts horizontally. Draw line Y = 7 to the left of line X = 3.
3. Point (17, 15) will divide the space to the right of line X = 3 into
two parts horizontally. Draw line Y = 15 to the right of line X =
3.
4. Point (6, 12) will divide the space below line Y = 15 and to the
right of line X = 3 into two parts. Draw line X = 6 to the right of
line X = 3 and below line Y = 15.
5. Point (13, 15) will divide the space below line Y = 15 and to
the right of line X = 6 into two parts. Draw line X = 13 to the
right of line X = 6 and below line Y = 15.
6. Point (9, 1) will divide the space between lines X = 3, X = 6
and Y = 15 into two parts. Draw line Y = 1 between lines X = 3
and X = 13.
X axis
7. Point (10, 19) will divide the space to the right of line X = 3
and above line Y = 15 into two parts. Draw line Y = 19 to the
right of line X = 3 and above line Y = 15.
Advantages of K Dimension Trees
• Efficient search: K-D trees are effective in searching for points in k-dimensional space,
such as in nearest neighbor search or range search.
• Dimensionality reduction: K-D trees can be used to reduce the dimensionality of the
problem, allowing for faster search times and reducing the memory requirements of the
data structure.
• Versatility: K-D trees can be used for a wide range of applications, such as in data
mining, computer graphics, and scientific computing.
• Balance: K-d trees are self-balancing, which ensures that the tree remains efficient
even when data is inserted or removed.
• Incremental construction: K-D trees can be incrementally constructed, which means
that data can be added or removed from the structure without having to rebuild the
entire tree.
• Easy to implement: K-D trees are relatively easy to implement and can be
implemented in a variety of programming languages.
SPLAY TREES

• Splay trees are a form of BSTs.


• A splay tree maintains a balance without any explicit balance condition such as color.
• Splay tree is a self-adjusting binary search tree data structure, which means that the tree
structure is adjusted dynamically based on the accessed or inserted elements.
• Splay Tree is a self - adjusted Binary Search Tree in which every operation on element
rearranges the tree so that the element is placed at the root position of the tree.
• In a splay tree, every operation is performed at the root of the tree. All the
operations in splay tree are involved with a common operation called "Splaying".
• Splaying is a process of restructuring the tree by making the most recently
accessed or inserted element the new root and gradually moving the remaining
nodes closer to the root.
• Splay trees are highly efficient in practice due to their self-adjusting nature, which
reduces the overall access time for frequently accessed elements.
• However, the main disadvantage of splay trees is that they do not guarantee a balanced
tree structure, which may lead to performance degradation in worst-case scenarios.
Operations in a splay tree:
Every operation on splay tree performs the splaying operation. For example, the insertion operation first

inserts the new element using the binary search tree insertion process, then the newly inserted element is

splayed so that it is placed at the root of the tree. The search operation in a splay tree is nothing but

searching the element using binary search process and then splaying that searched element so that it is

placed at the root of the tree.

1. Insertion: To insert a new element into the tree, start by performing a regular binary search tree

insertion. Then, apply rotations to bring the newly inserted element to the root of the tree.

2. Deletion: To delete an element from the tree, first locate it using a binary search tree search. Then, if

the element has no children, simply remove it. If it has one child, promote that child to its position in

the tree. If it has two children, find the successor of the element (the smallest element in its right

subtree), swap its key with the element to be deleted, and delete the successor instead.

3. Search: To search for an element in the tree, start by performing a binary search tree search. If the

element is found, apply rotations to bring it to the root of the tree. If it is not found, apply rotations to

the last node visited in the search, which becomes the new root.

4. Rotation: The rotations used in a splay tree are either a Zig or a Zig-Zig rotation. A Zig rotation is

used to bring a node to the root, while a Zig-Zig rotation is used to balance the tree after multiple
Rotations in Splay Tree
1. Zig Rotation
2. Zag Rotation
3. Zig - Zig Rotation
4. Zag - Zag Rotation
5. Zig - Zag Rotation
6. Zag - Zig Rotation

Zig Rotation - The Zig Rotation in splay tree is similar to the single right rotation in AVL Tree rotations.
In zig rotation, every node moves one position to the right from its current position. Consider the
following example...
Zag Rotation - The Zag Rotation in splay tree is similar to the single left rotation in AVL Tree rotations. In
zag rotation, every node moves one position to the left from its current position. Consider the following
example...

Zig-Zig Rotation -The Zig-Zig Rotation in splay tree is a double zig rotation. In zig-zig rotation, every node
moves two positions to the right from its current position. Consider the following example...
Zag-Zag Rotation - The Zag-Zag Rotation in splay tree is a double zag rotation. In zag-zag rotation, every
node moves two positions to the left from its current position. Consider the following example...

Zig-Zag Rotation - The Zig-Zag Rotation in splay tree is a sequence of zig rotation followed by zag
rotation. In zig-zag rotation, every node moves one position to the right followed by one position to the left
from its current position. Consider the following example...
Zag-Zig Rotation -The Zag-Zig Rotation in splay tree is a sequence of zag rotation followed
by zig rotation. In zag-zig rotation, every node moves one position to the left followed by one
position to the right from its current position. Consider the following example...

• Insertion Operation in Splay Tree


• The insertion operation in Splay tree is performed using following steps...
• Step 1 - Check whether tree is Empty.
• Step 2 - If tree is Empty then insert the newNode as Root node and exit from the operation.
• Step 3 - If tree is not Empty then insert the newNode as leaf node using Binary Search tree
insertion logic.
• Step 4 - After insertion, Splay the newNode
• Deletion Operation in Splay Tree
• The deletion operation in splay tree is similar to deletion operation in Binary Search Tree. But before
deleting the element, we first need to splay that element and then delete it from the root position.
Finally join the remaining tree using binary search tree logic.
Advantages of Splay Trees:
• Splay trees have amortized time complexity of O(log n) for many
operations, making them faster than many other balanced tree data
structures in some cases.
• Splay trees are self-adjusting, meaning that they automatically balance
themselves as items are inserted and removed. This can help to avoid the
performance degradation that can occur when a tree becomes unbalanced.

Disadvantages of Splay Trees:


• Splay trees can have worst-case time complexity of O(n) for some
operations, making them less predictable than other balanced tree data
structures like AVL trees or red-black trees.
• Splay trees may not be suitable for certain applications where predictable
performance is required.
Applications of the splay tree:
• Caching: Splay trees can be used to implement cache memory management, where the
most frequently accessed items are moved to the top of the tree for quicker access.
• Database Indexing: Splay trees can be used to index databases for faster searching and
retrieval of data.
• File Systems: Splay trees can be used to store file system metadata, such as the
allocation table, directory structure, and file attributes.
• Data Compression: Splay trees can be used to compress data by identifying and
encoding repeating patterns.
• Text Processing: Splay trees can be used in text processing applications, such as
spell-checkers, where words are stored in a splay tree for quick searching and retrieval.
• Graph Algorithms: Splay trees can be used to implement graph algorithms, such as
finding the shortest path in a weighted graph.
• Online Gaming: Splay trees can be used in online gaming to store and manage high
scores, leaderboards, and player statistics.

You might also like