You are on page 1of 72

Data Structures and

Algorithms (DSA)
Dr Suryaprakash Kompalli
Agenda
• Introduction to the Tree Data Structure
• Binary Search Trees
• Red-Black Trees
• Adelson-Velskii and Landis (AVL) Trees
• Other structures:
– Trie, Min/Max heap, B-Trees
Introduction to Tree Data Structure

• The tree is a hierarchical structure of child nodes connected to parent nodes


– Root / Head: Topmost or first node of a tree
9
– Depth of a node: Number of edges from root to that node. E.g.: Depth of node “4” is 2
– Height of node: Number of edges from this node to the farthest child 3 19
– Height of a tree is same as height of root nodes 1 4 21
Example tree: 9 is the parent of nodes 3 and 19. 3 is the
parent of 1 and 4. 19 is the parent of 21. 3 and 19 are the
children of 9, and so on.
Introduction to Tree Data Structure

• The tree is a hierarchical structure of child nodes connected to parent nodes


– Root / Head: Topmost or first node of a tree D: 0, H: 2
9
– Depth of a node: Number of edges from root to that node. E.g.: Depth of node “4” is 2
– Height of node: Number of edges from this node to the farthest child 3 D: 1, H: 1
19 D: 1, H: 1

D: 2, H: 0 D: 2, H: 0 D: 2, H: 0
– Height of a tree is same as height of root node 1 4 21
Example tree: 9 is the parent of nodes 3 and 19. 3 is the
parent of 1 and 4. 19 is the parent of 21. 3 and 19 are the
children of 9, and so on.

PS: Depth and Height are shown in the gray box.


Introduction to Tree Data Structure

• The tree is a hierarchical structure of child nodes connected to parent nodes


• How is a tree stored? 9
D: 0, H: 2

– Pointers
class TreeNode{
3 D: 1, H: 1
19 D: 1, H: 1

protected:
int value; D: 2, H: 0 D: 2, H: 0 D: 2, H: 0
TreeNode* ptrToLeftChild; 1 4 21
TreeNode* ptrToRightChild;
};
Example tree: 9 is the parent of nodes 3 and 19. 3 is the
Data structure where a parent can parent of 1 and 4. 19 is the parent of 21. 3 and 19 are the
have at max 2 children children of 9, and so on.

class TreeNode{ PS: Depth and Height are shown in the gray box.
protected:
int value;
TreeNode** ptrToChildren;
};
Data structure where a parent can
have more than 2 children

– If a particular pointer is NULL, then there is no child at that pointer


– In this example the “value” is an int. In practice, it can be any data structure. In most practical implementations,
the “value” should be a data structure that can be compared.
Introduction to Tree Data Structure

• The tree is a hierarchical structure of child nodes connected to parent nodes


• How is a tree stored? void TreeNode::deleteLeftChild(){
if (ptrToLeftChild != NULL){
9
ptrToLeftChild->deleteLeftChild();
D: 0, H: 2

ptrToLeftChild->deleteRightChild();
– Pointers ptrToLeftChild = NULL;
} 3
D: 1, H: 1
19 D: 1, H: 1

};
void TreeNode::deleteRightChild(){ D: 2, H: 0 D: 2, H: 0 D: 2, H: 0
if (ptrToRightChild != NULL){
class TreeNode{
protected: ptrToRightChild->deleteLeftChild(); 1 4 21
int value; ptrToRightChild->deleteRightChild();
TreeNode* ptrToLeftChild; ptrToRightChild = NULL; Example tree: 9 is the parent of nodes 3 and 19. 3 is the
TreeNode* ptrToRightChild; }
};
parent of 1 and 4. 19 is the parent of 21. 3 and 19 are the
};
void TreeNode::setLeftChild(TreeNode* inLeftChild){ children of 9, and so on.
Data structure where a parent can if (ptrToLeftChild != NULL){
have at max 2 children char* message = new char[2048];
sprintf(message, "A left child already exists. This is an illegal state");
throw std::logic_error(message);
delete []message;
}
ptrToLeftChild = inLeftChild;
};
void TreeNode::setRightChild(TreeNode* inRightChild){
The code given on right if (ptrToRightChild != NULL){
char* message = new char[2048];
side maintains the tree sprintf(message, "A right child already exists. This is an illegal state");
throw std::logic_error(message);
data structure. There may delete []message;
}
be additional conditions ptrToRightChild = inRightChild;
depending on the type of };

tree – BST, Red-Black etc


Introduction to Tree Data Structure

• The tree is a hierarchical structure of child nodes connected to parent nodes


• How is a tree stored? 9
D: 0, H: 2

– Pointers
3 D: 1, H: 1
19 D: 1, H: 1

D: 2, H: 0 D: 2, H: 0 D: 2, H: 0
class TreeNode{
protected: 1 4 21
int value;
TreeNode* ptrToLeftChild; Example tree: 9 is the parent of nodes 3 and 19. 3 is the
TreeNode* ptrToRightChild; parent of 1 and 4. 19 is the parent of 21. 3 and 19 are the
};
children of 9, and so on.
void printTree(int offsetToPrint){
Data structure where a parent can offsetToPrint += offset_increment;
have at max 2 children if (this->ptrToRightChild != NULL)
this->ptrToRightChild->printTree(offsetToPrint);
std::string message;
int height = 0;
for (int i = offset_increment; i < offsetToPrint; i++){
height += 1;
message += "\t";
}
The code given on right char intValue[30];
sprintf(intValue, "%d, h=%d", this->value, height/offset_increment);
side prints the tree message += intValue;
structure. LogManager::writePrintfToLog(LogManager::Status, "TreeNode::printTree",
"%s", message.c_str());

if (this->ptrToLeftChild != NULL)
this->ptrToLeftChild->printTree(offsetToPrint);
}
Introduction to Tree Data Structure

• The tree is a hierarchical structure of child nodes connected to parent nodes


• How is a tree stored?
void TreeNode::deleteLeftChild(){
if (ptrToLeftChild != NULL){ D: 0, H: 2
9
ptrToLeftChild->deleteLeftChild();
ptrToLeftChild->deleteRightChild();
– Pointers ptrToLeftChild = NULL;

};
}
3
D: 1, H: 1
19 D: 1, H: 1

void TreeNode::deleteRightChild(){
if (ptrToRightChild != NULL){ D: 2, H: 0 D: 2, H: 0 D: 2, H: 0
class TreeNode{
protected:
ptrToRightChild->deleteLeftChild();
ptrToRightChild->deleteRightChild();
1 4 21
int value; ptrToRightChild = NULL;
TreeNode* ptrToLeftChild; } Example tree: 9 is the parent of nodes 3 and 19. 3 is the
TreeNode* ptrToRightChild; }; parent of 1 and 4. 19 is the parent of 21. 3 and 19 are the
}; void TreeNode::setLeftChild(TreeNode* inLeftChild){ children of 9, and so on.
Data structure where a parent can if (ptrToLeftChild != NULL){
char* message = new char[2048];
have at max 2 children
sprintf(message, "A left child already exists. This is an illegal state");
throw std::logic_error(message);
class TreeNode{ delete []message;
protected: }
int value; ptrToLeftChild = inLeftChild;
TreeNode** ptrToChildren; };
}; void TreeNode::setRightChild(TreeNode* inRightChild){
if (ptrToRightChild != NULL){
Data structure where a parent can char* message = new char[2048];
have more than 2 children sprintf(message, "A right child already exists. This is an illegal state");
throw std::logic_error(message);
delete []message;
The code given on create }
ptrToRightChild = inRightChild;
or print a tree will have to };
be modified if a node has
more than 2 children.
Introduction to Tree Data Structure

• The tree is a hierarchical structure of child nodes connected to parent nodes


• How is a tree stored? 9
D: 0, H: 2

– Arrays
3 D: 1, H: 1
19 D: 1, H: 1

D: 2, H: 0 D: 2, H: 0 D: 2, H: 0

Index: 0 1 2 3 4 5 6 7 1 4 21
Example tree: 9 is the parent of nodes 3 and 19. 3 is the
Value: 9 3 19 1 4 NULL 21 NULL parent of 1 and 4. 19 is the parent of 21. 3 and 19 are the
children of 9, and so on.
If index of parent is “p”, index of left child is: 2p + 1, index of
right child is: 2p + 2.

Eg:
Index of 9 is 0, indices of it’s children are: 1, 2.
Index of 3 is 1, indices of it’s children are: 3, 4.
Index of 19 is 2, indices of it’s children are: 5, 6.
Introduction to Tree Data Structure

• The tree is a hierarchical structure of child nodes connected to parent nodes


• How is a tree stored? 9
D: 0, H: 2

– Arrays
3 D: 1, H: 1
19 D: 1, H: 1

D: 2, H: 0 D: 2, H: 0 D: 2, H: 0

Index: 0 1 2 3 4 5 6 7 1 4 21
Example tree: 9 is the parent of nodes 3 and 19. 3 is the
Value: 9 3 19 1 4 NULL 21 NULL parent of 1 and 4. 19 is the parent of 21. 3 and 19 are the
children of 9, and so on.
If index of parent is “p”, index of left child is: 2p + 1, index of
right child is: 2p + 2.

Eg: Note:
Index of 9 is 0, indices of it’s children are: 1, 2. This formulation assumes that the index starts from 0. The
Index of 3 is 1, indices of it’s children are: 3, 4. formulation to get indices will be different if the starting
Index of 19 is 2, indices of it’s children are: 5, 6. index is not zero.

Using arrays can lead to a wastage of memory, especially if


the tree has several one-sided branches. In this course, we
will focus on using pointers to build trees.
Agenda
• Introduction to the Tree Data Structure
• Binary Search Trees
• Red-Black Trees
• Adelson-Velskii and Landis (AVL) Trees
• Other structures:
– Trie, Min/Max heap, B-Trees
Binary Search Trees (BSTs)
9
• Each node in a BST is such that:
3 19
– The left child is smaller than or equal to the parent node
1 4 21
– The right child is greater than the parent node
Is this a BST?
Binary Search Trees (BSTs)
9
• Each node in a BST is such that:
3 19
– The left child is smaller than or equal to the parent node
1 4 21
– The right child is greater than the parent node
Is this a BST? Yes !!!
Binary Search Trees (BSTs)
9
• Each node in a BST is such that:
3 19
– The left child is smaller than or equal to the parent node
1 4 21
– The right child is greater than the parent node

• The BST has some interesting properties: Is this a BST? Yes !!!

– Height of a randomly built BST is O(lg n)


– An “Inorder tree walk” routine can be implemented on the BST to print values in increasing order
– Searching for a value, finding the minimum, maximum, successor, or predecessor in a BST takes O(h),
on a tree with height h

• Code for inserting values into a tree has to be changed so that the
BST property is maintained
Binary Search Trees (BSTs)
• Code for inserting values into a tree has to be changed so that the
BST property is maintained.
class BinarySearchTreeNode : public TreeNode{
public:

BinarySearchTreeNode(int inValue) : TreeNode(inValue){


};
void addChild(int inValue);
};

class TreeNode{
protected:
int value;
TreeNode* ptrToLeftChild;
TreeNode* ptrToRightChild;
};

In this example, we have derived a class


of type BinarySearchTreeNode from the
TreeNode.
Binary Search Trees (BSTs)
• Code for inserting values into a tree has to be changed so that the
BST property is maintained.
class BinarySearchTreeNode : public TreeNode{ void BinarySearchTreeNode::addChild(int inValue){
public: if (inValue <= this->value){
if (this->ptrToLeftChild != NULL){
BinarySearchTreeNode(int inValue) : TreeNode(inValue){ this->ptrToLeftChild->addChild(inValue);
}; return;
void addChild(int inValue); }
}; BinarySearchTreeNode* newNode = new BinarySearchTreeNode(inValue);
this->setLeftChild(newNode);
}else{
if (this->ptrToRightChild != NULL){
this->ptrToRightChild->addChild(inValue);
return;
}
class TreeNode{ BinarySearchTreeNode* newNode = new BinarySearchTreeNode(inValue);
protected: this->setRightChild(newNode);
int value; }
TreeNode* ptrToLeftChild; }
TreeNode* ptrToRightChild;
};

In this example, we have derived a class The addChild function shown above adds a new node while
of type BinarySearchTreeNode from the maintaining the Binary Search Tree property:
TreeNode. • The left child is smaller than or equal to the parent node
• The right child is greater than the parent node

(Note: In this implementation, the right child will always be greater)


Binary Search Trees (BSTs)
• Code for inserting values into a tree has to be changed so that the
BST property is maintained.
class BinarySearchTreeNode : public TreeNode{ static BinarySearchTreeNode* buildTree(int* inArray, int countOfElements){
public: BinarySearchTreeNode * headNode = new BinarySearchTreeNode(inArray[0]);
for (int i=1; i<countOfElements; i++)
BinarySearchTreeNode(int inValue) : TreeNode(inValue){ headNode->addChild(inArray[i]);
}; return headNode;
void addChild(int inValue); };
};

class TreeNode{
protected:
int value;
TreeNode* ptrToLeftChild;
TreeNode* ptrToRightChild;
};

In this example, we have derived a class The buildTree function shown above takes as
of type BinarySearchTreeNode from the input an array of integer values and the number of
TreeNode. integers. It builds a BST by using the addChild
function, and returns the “root” or “head” node of
the tree.

The function below prints out the tree.


Binary Search Trees (BSTs)
• Code for inserting values into a tree has to be changed so that the
BST property is maintained.
int BinarySearchTreeNode::getMinimum(){
if (this->ptrToLeftChild != NULL)
Due to the BST property, searching if a value
this->ptrToLeftChild->getMinimum(); is present in the tree or not will take ϴ(lg h),
LogManager::writePrintfToLog(LogManager::Status, "BinarySearchTreeNode::getMinimum", here h is height of the tree.
"Minimum value=%d", this->value);
}

int BinarySearchTreeNode::getMaximum(){
if (this->ptrToRightChild != NULL) Finding the maximum, minimum will take
this->ptrToRightChild->getMinimum(); O(h)
LogManager::writePrintfToLog(LogManager::Status, "BinarySearchTreeNode::getMaximum",
"Minimum value=%d", this->value);
} A successor of an int value is the smallest
element of the tree that is larger than the int
bool BinarySearchTreeNode::isPresent(int inValue){
if (this->value == inValue) value.
return true;
if (this->value < inValue)
if (this->ptrToLeftChild != NULL)
return ((BinarySearchTreeNode*) this->ptrToLeftChild)->isPresent(inValue);
else A predecessor of an int value is the largest
return false; element of the tree that is smaller than the
else
if (this->ptrToRightChild != NULL) int value.
return ((BinarySearchTreeNode*) this->ptrToRightChild)->isPresent(inValue);
else
return false; Finding successor or predecessor can also be
}
implemented in O(h)

Are there any errors on this slide?


Binary Search Trees (BSTs)
• Code for inserting values into a tree has to be changed so that the
BST property is maintained.
int BinarySearchTreeNode::getMinimum(){
if (this->ptrToLeftChild != NULL)
Due to the BST property, searching if a value
this->ptrToLeftChild->getMinimum(); is present in the tree or not will take ϴ(lg h),
LogManager::writePrintfToLog(LogManager::Status, "BinarySearchTreeNode::getMinimum", here h is height of the tree.
"Minimum value=%d", this->value);
}

int BinarySearchTreeNode::getMaximum(){
if (this->ptrToRightChild != NULL) Finding the maximum, minimum will take
this->ptrToRightChild->getMinimum(); O(h)
LogManager::writePrintfToLog(LogManager::Status, "BinarySearchTreeNode::getMaximum",
"Minimum value=%d", this->value);
} A successor of an int value is the smallest
element of the tree that is larger than the int
bool BinarySearchTreeNode::isPresent(int inValue){
if (this->value == inValue) value.
return true;
if (this->value < inValue)
if (this->ptrToLeftChild != NULL)
return ((BinarySearchTreeNode*) this->ptrToLeftChild)->isPresent(inValue);
else A predecessor of an int value is the largest
return false; element of the tree that is smaller than the
else
if (this->ptrToRightChild != NULL) int value.
return ((BinarySearchTreeNode*) this->ptrToRightChild)->isPresent(inValue);
else
return false; Finding successor or predecessor can also be
}
implemented in O(h)

Are there any errors on this slide?


Binary Search Trees (BSTs)
• Code for inserting values into a tree has to be changed so that the
BST property is maintained.
int BinarySearchTreeNode::getMinimum(){
if (this->ptrToLeftChild != NULL)
Due to the BST property, searching if a value
this->ptrToLeftChild->getMinimum(); is present in the tree or not will take O(h),
LogManager::writePrintfToLog(LogManager::Status, "BinarySearchTreeNode::getMinimum", here h is height of the tree.
"Minimum value=%d", this->value);
}

int BinarySearchTreeNode::getMaximum(){
if (this->ptrToRightChild != NULL) Finding the maximum, minimum will take
this->ptrToRightChild->getMaximum(); O(h)
LogManager::writePrintfToLog(LogManager::Status, "BinarySearchTreeNode::getMaximum",
"Maximum value=%d", this->value);
} A successor of an int value is the smallest
element of the tree that is larger than the int
bool BinarySearchTreeNode::isPresent(int inValue){
if (this->value == inValue) value.
return true;
if (this->value < inValue)
if (this->ptrToLeftChild != NULL)
return ((BinarySearchTreeNode*) this->ptrToLeftChild)->isPresent(inValue);
else A predecessor of an int value is the largest
return false; element of the tree that is smaller than the
else
if (this->ptrToRightChild != NULL) int value.
return ((BinarySearchTreeNode*) this->ptrToRightChild)->isPresent(inValue);
else
return false; Finding successor or predecessor can also be
}
implemented in O(h)
Binary Search Trees (BSTs)
9
• Efficiency is dependent on the sequence of inserting values
3 19
– E.g: The tree shown as example here is obtained if the integers are inserted
in the following sequence: 9, 3, 19, 1, 4, 21. 1 4 21
– If values are inserted in the following sequence: 1, 19, 4, 3, 9, 21, the Is this a BST? Yes !!!
following BST is obtained:
1

19

4 21

3 9
Is this a BST? Yes !!!
Binary Search Trees (BSTs)
9
• Efficiency is dependent on the sequence of inserting values
3 19
– E.g: The tree shown as example here is obtained if the integers are inserted
in the following sequence: 9, 3, 19, 1, 4, 21. 1 4 21
– If values are inserted in the following sequence: 1, 19, 4, 3, 9, 21, the Is this a BST? Yes !!!
following BST is obtained:
1

19

4 21

3 9
Is this a BST? Yes !!!

– In a worst case situation, height of the tree can be equal to number of


elements inserted into the tree. When can this happen?
Binary Search Trees (BSTs)
9
• Efficiency is dependent on the sequence of inserting values
3 19
– E.g: The tree shown as example here is obtained if the integers are inserted
in the following sequence: 9, 3, 19, 1, 4, 21. 1 4 21
– If values are inserted in the following sequence: 1, 19, 4, 3, 9, 21, the Is this a BST? Yes !!!
following BST is obtained:
1

19

4 21

3 9
Is this a BST? Yes !!!

– In a worst case situation, height of the tree can be equal to number of


elements inserted into the tree. When can this happen?
– When all elements are inserted in a sorted order: increasing or decreasing
Agenda
• Introduction to the Tree Data Structure
• Binary Search Trees
• Red-Black Trees
• Adelson-Velskii and Landis (AVL) Trees
• Other structures:
– Trie, Min/Max heap, B-Trees
Red-Black Trees
9
• The efficiency of a BST is dependent on the sequence of
3 19
inserting values
– E.g: The tree shown as example here is obtained if the integers are inserted 1 4 21
in the following sequence: 9, 3, 19, 1, 4, 21. Is this a BST? Yes !!!
– If values are inserted in the following sequence: 1, 19, 4, 3, 9, 21, the
following BST is obtained: 1

19

4 21

3 9
Is this a BST? Yes !!!

– Red-Black trees are BST with an additional bit on each Node: color Red/
Black. If the bit is zero the node is Red. If the bit is one, the node is black
– Constraints on the colors present on a path from root to each leaf prevent a
leaf from from having more than twice the depth of any other leaf. This
makes Red-Black trees become approximately balanced, and hence more
efficient than BSTs
Red-Black Trees
9
• Constraints placed on Red-Black tree
3 19
1) Every node must have one color – red or black
1 4 21
2) Root node is black
3) All Leaf nodes must be black Is this a Red-Black tree? Yes !!!

4) If a node is red, both children are black


1
5) All paths from a node to its’ leaf nodes must have same number of black
nodes 19

9 21

4
Is this a Red-black tree? Not quite.
Number of black nodes between node 1
to 4 is more than from node 1 to 21.
Red-Black Trees
9
• Rotate operations used to modify red-black trees
3 19
19 4
Right-rotate(T, 19) 1 4 21
4 21 3 19
Is this a Red-Black tree? Yes !!!
3 9 9 21
In Right-rotate, the node on which you perform rotation is moved to the
right side of the tree. In this case, 19 is moved to the right. In order to
maintain BST condition, Note that 4 becomes the parent of 3 and 19. 9
becomes the child of 19.

4 19
3 19 4
Left-rotate(T, 4) 21
9 21 3 9
In Left-rotate, the node on which you perform rotation is moved to the left
side of the tree. In this case, 4 is moved to the left. In order to maintain
BST condition, 4 becomes the parent of 3 and 9. 19 becomes the parent
of 4 and 21.
Red-Black Trees
9
• Left-rotate and Right-rotate operations
3 19
Why are these operations useful? Using these operations, an unbalanced BST
can be converted to a balanced BST. i.e. a Tree that violates Red-black 1 4 21
conditions can be converted to a tree that follows Red-black constraints
Is this a Red-Black tree? Yes !!!
For example, consider the leftmost tree below. It is not a RedBlack tree. It can be
converted into a RedBlack tree by right-rotate and left-rotate operations.

19

9 21

4
Is this a Red-black tree? Not quite.
Number of black nodes between node 1
to 4 is more than from node 1 to 21.
Red-Black Trees
9
• Left-rotate and Right-rotate operations
3 19
Why are these operations useful? Using these operations, an unbalanced BST
can be converted to a balanced BST. i.e. a Tree that violates Red-black 1 4 21
conditions can be converted to a tree that follows Red-black constraints
Is this a Red-Black tree? Yes !!!
For example, consider the leftmost tree below. It is not a RedBlack tree. It can be
converted into a RedBlack tree by right-rotate and left-rotate operations.

19
1
9 21
Right-rotate(T, 19) 9
3
3 19
4
4 21
Is this a Red-black tree? Not quite.
Number of black nodes between node 1 Is this a Red-black tree? Yes !!!
to 4 is more than from node 1 to 21. While 4 and 9 are not black nodes, they can be
connected to “NULL” or dumy nodes which can
be marked black.
RedBlackTreeNode* RedBlackTree::addChild(int inValue, RedBlackTreeNode* possibleParent){

Red-Black Trees if (inValue == possibleParent->nodeValue) // Do not add the node if it already exists.
return NULL;

if (inValue < possibleParent->getValue()){

• Five constraints are placed on Red-Black tree if (possibleParent->leftChild != NULL){

}
return addChild(inValue, possibleParent->leftChild);

RedBlackTreeNode* currNode = new RedBlackTreeNode(inValue);


possibleParent->leftChild = currNode;
1) Every node must have one color – red or black currNode->parent = possibleParent;
return currNode;
}else{
2) Root node is black if (possibleParent->rightChild != NULL){
return addChild(inValue, possibleParent->rightChild);
}
RedBlackTreeNode* currNode = new RedBlackTreeNode(inValue);
3) All Leaf nodes must be black possibleParent->rightChild = currNode;
currNode->parent = possibleParent;
return currNode;
4) If a node is red, both children are black }
}

5) All paths from a node to its’ leaf nodes must have same number of black nodes

• Insertion operation can be designed so that it violates only rules 2 or 4; how?


– When a value is inserted into a RedBlack tree, the initial node is created using a process similar to the operation in
BST. This initial insert into the tree creates a new “red” node only at the root or at the leaf.

Also check the code for:

static RedBlackTree* buildTree(int* inArray, int countOfElements)


RedBlackTreeNode* RedBlackTree::addChild(int inValue, RedBlackTreeNode* possibleParent){

Red-Black Trees if (inValue == possibleParent->nodeValue) // Do not add the node if it already exists.
return NULL;

if (inValue < possibleParent->getValue()){

• Five constraints are placed on Red-Black tree if (possibleParent->leftChild != NULL){

}
return addChild(inValue, possibleParent->leftChild);

RedBlackTreeNode* currNode = new RedBlackTreeNode(inValue);


possibleParent->leftChild = currNode;
1) Every node must have one color – red or black currNode->parent = possibleParent;
return currNode;
}else{
2) Root node is black if (possibleParent->rightChild != NULL){
return addChild(inValue, possibleParent->rightChild);
}
RedBlackTreeNode* currNode = new RedBlackTreeNode(inValue);
3) All Leaf nodes must be black possibleParent->rightChild = currNode;
currNode->parent = possibleParent;
return currNode;
4) If a node is red, both children are black }
}

5) All paths from a node to its’ leaf nodes must have same number of black nodes

• Insertion operation can be designed so that it violates only rules 2 or 4; how?


– When a value is inserted into a RedBlack tree, the initial node is created using a process similar to the operation in
BST. This initial insert into the tree creates a new “red” node only at the root or at the leaf.
– If no root node existed, the new node is the root and has red color, it will violate property 2.
– If a node is inserted as a new leaf, then it does not violate properties 2. A special “NULL” node with black color can
be attached to the new leaf node so that property 3 is not violated. Property 4 may be violated if the parent of this
new leaf is a red node. Property 5 cannot be violated because the new leaf is added to a parent which is already part
of a Red-Black tree. By definition, a path to this parent has the same number of black nodes as to any other parent.

• Rotations and color changes in a specific sequence can fix violations to rules 2
and 4
Red-Black Trees
• Five constraints are placed on Red-Black tree
1) Every node must have one color – red or black
2) Root node is black
3) All Leaf nodes must be black
4) If a node is red, both children are black
5) All paths from a node to its’ leaf nodes must have same number of black nodes

• Three cases emerge where tree has to be adjusted/fixed:


– Nomenclature; z: Node to be fixed, z.p: parent of z, z.p.p, grandfather of z, y: The sibling of z.p, or the other child of
z.p.p.
– z.p can either be the left child or right child of z.p.p (Case 1 to Case 3 can occur in both of these situations)
– Case 1: z.color is red. z.p.color is red. y.color is red.
– Case 2: z.color is red. z.p.color is red. y.color is black. z is right child of z.p
– Case 3: z.color is red. z.p.color is red. y.color is black. z is left child of z.p
– Default step: Change the root node to black color
Red-Black Trees
• Five constraints are placed on Red-Black tree
1) Every node must have one color – red or black Inserting a new node “z” can violate
property 2 or 4
2) Root node is black
3) All Leaf nodes must be black
4) If a node is red, both children are black
5) All paths from a node to its’ leaf nodes must have same number of black nodes

• Three cases emerge where tree has to be adjusted/fixed:


– Nomenclature; z: Node to be fixed, z.p: parent of z, z.p.p, grandfather of z, y: The sibling of z.p, or the other child of
z.p.p.
– z.p can either be the left child or right child of z.p.p (Case 1 to Case 3 can occur in both of these situations)
– Case 1: z.color is red. z.p.color is red. y.color is red.
– Case 2: z.color is red. z.p.color is red. y.color is black. z is right child of z.p
– Case 3: z.color is red. z.p.color is red. y.color is black. z is left child of z.p
– Default step: Change the root node to black color
Red-Black Trees
• Five constraints are placed on Red-Black tree
1) Every node must have one color – red or black Inserting a new node “z” can violate
property 2 or 4
2) Root node is black
3) All Leaf nodes must be black
4) If a node is red, both children are black
5) All paths from a node to its’ leaf nodes must have same number of black nodes

• Three cases emerge where tree has to be adjusted/fixed:


– Nomenclature; z: Node to be fixed, z.p: parent of z, z.p.p, grandfather of z, y: The sibling of z.p, or the other child of
z.p.p.
– z.p can either be the left child or right child of z.p.p (Case 1 to Case 3 can occur in both of these situations)
– Case 1: z.color is red. z.p.color is red. y.color is red. In a Red-Black tree, both children are
supposed to have same color. So Case 2,
– Case 2: z.color is red. z.p.color is red. y.color is black. z is right child of z.p 3 will not occur immidiately after insertion.

Case 2, 3 may occur after one loop of


– Case 3: z.color is red. z.p.color is red. y.color is black. z is left child of z.p node-adjustment is performed. The parent
color may change during the adjustment
– Default step: Change the root node to black color process. At that time, child nodes may
have different colors, leading to this
situation.
Red-Black Trees
• Three cases emerge where tree has to be adjusted/fixed:
– Nomenclature; z: Node to be fixed, z.p: parent of z, z’=z.p.p, grandfather of z, y: The sibling of z.p, or the other child
of z’.
– Case 1: z.color is red. z.p.color is red. y.color is red.
– Case 2: z.color is red. z.p.color is red. y.color is black. z is right child of z.p
– Case 3: z.color is red. z.p.color is red. y.color is black. z is left child of z.p
– RB-Insert-Fixup ensures Red-Black tree conditions are satisfied

• Steps in case 1:
– Set z.p and y to black
– z.p.p is set to red
– z = z.p.p; while loop continues

• Result of case 1:
– Below z.p.p, the Red-Black condition is satisfied
– Due to z.p.p becoming red color, it is possible that the
Red-Black condition may be violated if z.p.p is root node,
or z.p.p.p has red color. Fixup will be called on z.p.p
Red-Black Trees
• Three cases emerge where tree has to be adjusted/fixed:
– Nomenclature; z: Node to be fixed, z.p: parent of z, z’=z.p.p, grandfather of z, y: The sibling of z.p, or the other child
of z’.
– Case 1: z.color is red. z.p.color is red. y.color is red.
– Case 2: z.color is red. z.p.color is red. y.color is black. z is right child of z.p z.p.p
– Case 3: z.color is red. z.p.color is red. y.color is black. z is left child of z.p z.p y
– RB-Insert-Fixup ensures Red-Black tree conditions are satisfied
z
• Steps in case 1: Sample sub-tree for case 1

– Set z.p and y to black


– z.p.p is set to red
– z = z.p.p; while loop continues
z.p.p
• Result of case 1:
– Below z.p.p, the Red-Black condition is satisfied z.p y
– Due to z.p.p becoming red color, it is possible that the
Red-Black condition may be violated if z.p.p is root node, z
Result of case 1
or z.p.p.p has red color. Fixup will be called on z.p.p
Red-Black Trees
• Three cases emerge where tree has to be adjusted/fixed:
– Nomenclature; z: Node to be fixed, z.p: parent of z, z’=z.p.p, grandfather of z, y: The sibling of z.p, or the other child
of z’.
– Case 1: z.color is red. z.p.color is red. y.color is red.
– Case 2: z.color is red. z.p.color is red. y.color is black. z is right child of z.p z.p.p
– Case 3: z.color is red. z.p.color is red. y.color is black. z is left child of z.p z.p y
– RB-Insert-Fixup ensures Red-Black tree conditions are satisfied
z
• Steps in case 1: Sample sub-tree for case 1

– Set z.p and y to black


While loop continues
with this node as the
– z.p.p is set to red “new” value of z
– z = z.p.p; while loop continues
z.p.p
• Result of case 1:
– Below z.p.p, the Red-Black condition is satisfied z.p y
– Due to z.p.p becoming red color, it is possible that the
Red-Black condition may be violated if z.p.p is root node, z
Result of case 1
or z.p.p.p has red color. Fixup will be called on z.p.p
Red-Black Trees
• Three cases emerge where adjustments need to be made to tree:
– Nomenclature; z: Node to be adjusted, z.p: parent of z, z’=z.p.p, grandfather of z, y: The sibling of z.p, or the other
child of z’.
– Case 1: z.color is red. z.p.color is red. y.color is red.
– Case 2: z.color is red. z.p.color is red. y.color is black. z is right child of z.p
– Case 3: z.color is red. z.p.color is red. y.color is black. z is left child of z.p

• Steps in case 3: (When case 2 is not applicable)


– z.p is set to black, z.p.p is set to red
– A right-rotate is performed on z.p.p
– While loop continues

• Result of case 3:
– z.p is black, z.p is parent of z.p.p and z which are red; if z.p
had a right child, it would be black and will be left child of z.p.p
Red-Black Trees
• Three cases emerge where adjustments need to be made to tree:
– Nomenclature; z: Node to be adjusted, z.p: parent of z, z’=z.p.p, grandfather of z, y: The sibling of z.p, or the other
child of z’.
– Case 1: z.color is red. z.p.color is red. y.color is red.
– Case 2: z.color is red. z.p.color is red. y.color is black. z is right child of z.p z.p.p
– Case 3: z.color is red. z.p.color is red. y.color is black. z is left child of z.p z.p y

• Steps in case 3: (When case 2 is not applicable) z


Sample sub-tree for case 3
– z.p is set to black, z.p.p is set to red
– A right-rotate is performed on z.p.p
– While loop continues

• Result of case 3: z.p


– z.p is black, z.p is parent of z.p.p and z which are red; if z.p
z z.p.p
had a right child, it would be black and will be left child of z.p.p
y
Result of case 3
Red-Black Trees
• Three cases emerge where adjustments need to be made to tree:
– Nomenclature; z: Node to be adjusted, z.p: parent of z, z’=z.p.p, grandfather of z, y: The sibling of z.p, or the other
child of z’.
– Case 1: z.color is red. z.p.color is red. y.color is red.
– Case 2: z.color is red. z.p.color is red. y.color is black. z is right child of z.p z.p.p
– Case 3: z.color is red. z.p.color is red. y.color is black. z is left child of z.p z.p y

• Steps in case 3: (When case 2 is not applicable) z


Sample sub-tree for case 3
– z.p is set to black, z.p.p is set to red
– A right-rotate is performed on z.p.p
This is the “new” value of z.
– While loop terminates But the color of z.p is black,
so the loop terminates

• Result of case 3:(When case 2 is not applicable) z.p


– z.p is black, z.p is parent of z.p.p and z which are red; if z.p
z z.p.p
had a right child, it would be black and will be left child of z.p.p
y
Result of case 3
Red-Black Trees
• Three cases emerge where adjustments need to be made to tree:
– Nomenclature; z: Node to be adjusted, z.p: parent of z, z’=z.p.p, grandfather of z, y: The sibling of z.p, or the other
child of z’.
– Case 1: z.color is red. z.p.color is red. y.color is red.
– Case 2: z.color is red. z.p.color is red. y.color is black. z is right child of z.p
– Case 3: z.color is red. z.p.color is red. y.color is black. z is left child of z.p

• Steps in case 2:
– Left-rotate is performed on z.p

• Result of case 2:
– z is now the left child of z.p.p
– z.p becomes the child of z
– Case 2 transforms into case 3.
Red-Black Trees
• Three cases emerge where adjustments need to be made to tree:
– Nomenclature; z: Node to be adjusted, z.p: parent of z, z’=z.p.p, grandfather of z, y: The sibling of z.p, or the other
child of z’.
– Case 1: z.color is red. z.p.color is red. y.color is red.
– Case 2: z.color is red. z.p.color is red. y.color is black. z is right child of z.p z.p.p
– Case 3: z.color is red. z.p.color is red. y.color is black. z is left child of z.p z.p y

• Steps in case 2: z
Sample sub-tree for case 2
– Left-rotate is performed on z.p

• Result of case 2:
– z is now the left child of z.p.p
– z.p becomes the child of z z.p.p
– Case 2 transforms into case 3.
z y

z.p
Result of case 2
Red-Black Trees
• Three cases emerge where adjustments need to be made to tree:
– Nomenclature; z: Node to be adjusted, z.p: parent of z, z’=z.p.p, grandfather of z, y: The sibling of z.p, or the other
child of z’.
z.p.p
– Case 1: z.color is red. z.p.color is red. y.color is red.
z.p y
– Case 2: z.color is red. z.p.color is red. y.color is black. z is right child of z.p
– Case 3: z.color is red. z.p.color is red. y.color is black. z is left child of z.p z
Sample sub-tree for case 2

• Steps in case 3: (After applying case 2)


– z.p (old z) is set to black, z.p.p is set to red
– Right-rotate is performed on z.p.p
z
– While loop continues z.p.p
z.p z.p.p
z y
y
z.p
• Result of case 3:(After applying case 2) Result of case 3 (after
applying case 2) Result of case 2

– z is black, z is parent of z.p.p and z which are red


Red-Black Trees
• Three cases emerge where adjustments need to be made to tree:
– Nomenclature; z: Node to be adjusted, z.p: parent of z, z’=z.p.p, grandfather of z, y: The sibling of z.p, or the other
child of z’.
z.p.p
– Case 1: z.color is red. z.p.color is red. y.color is red.
z.p y
– Case 2: z.color is red. z.p.color is red. y.color is black. z is right child of z.p
– Case 3: z.color is red. z.p.color is red. y.color is black. z is left child of z.p z
Sample sub-tree for case 2

• Steps in case 3: (After applying case 2) In the next iterataion of while loop
this node as the “new” value of z.
Note that in the new loop, the
parent of the new z is the parent
– z.p (old z) is set to black, z.p.p is set to red of previous z.p.p
– Right-rotate is performed on z.p.p
z
– While loop continues z.p.p
z.p z.p.p
z y
y
z.p
• Result of case 3:(After applying case 2) Result of case 3 (after
applying case 2) Result of case 2

– z is black, z is parent of z.p.p and z which are red


Red-Black Trees
• Three cases emerge where adjustments need to be made to tree:
z.p.p
z.p.p
y z.p.p
z.p y
z.p
z.p y
z
z
Sample sub-tree for case 1
Sample sub-tree for case 3 z
While loop continues Sample sub-tree for case 2
with this node as the While loop continues with this node as
“new” value of z the “new” value of z. Note that in the
new loop, parents and grand parents of
z will be different
This is the “new” value
z.p.p of z. But the color of z.p
is black, so the loop z.p z
terminates z.p.p
z.p y
z z.p.p z.p z.p.p
z y
z y y
Result of case 1
Result of case 3 z.p
Result of case 3 (after
applying case 2) Result of case 2

Case 1 Case 3 without the need to Case 3 after applying case 2


apply case 2
Red-Black Trees
• The insertion of a node into a RedBlack tree is made of two parts
• Finding the location where a node needs to be inserted.
– This can be performed in O(lg n) time.

• After a location is found, insert the node at that location. Correct violations in
the RedBlack properties by calling RB-Insert-Fixup
– This also takes O(lg n) time
Red-Black Trees
• Deletion of node from tree
– Deleting a node from a Red-Black tree may also need node adjustment

• Any violation of Red-Black tree properties can also be corrected using a


combination of rotation and color change operations
Agenda
• Introduction to the Tree Data Structure
• Binary Search Trees
• Red-Black Trees
• Adelson-Velskii and Landis (AVL) Trees
• Other structures:
– Trie, Min/Max heap, B-Trees
AVL Trees
• Similar to Red-Black Trees or Binary Search Trees with a Balancing condition
enforced
– At every parent, absolute difference of the height of left and right sub-tree can be 1
– This difference is called “balance factor” bf = (TL_height- TR_height)
– In AVL treees, abs(bf) ≤ 1

• How is balancing enforced?


• During insertion:
– Insertion performed just like in case of Binary Search Trees
– bf value for every node is updated
– If the value of any node is > 1, a series of rotations are performed
• Similar process is followed during deletion
AVL Trees
• Types of rotations:
– Single rotations: Left-Left (LL), Right-Right (RR)
– Double rotations: Left-Right (LR), Right-left (RL)
bf=-2
A
bf=0
B
B bf=-1
A bf=0 C bf=0
C bf=0

Left-Left (LL) at A
AVL Trees
• Types of rotations:
– Single rotations: Left-Left (LL), Right-Right (RR)
– Double rotations: Left-Right (LR), Right-left (RL)
bf=-2
A
bf=0
B
B bf=-1
A bf=0 C bf=0
C bf=0

Left-Left (LL) at A

The tree is imbalanced towards the Right side.


To balance this, rotate Left-Left
AVL Trees
• Types of rotations:
– Single rotations: Left-Left (LL), Right-Right (RR)
– Double rotations: Left-Right (LR), Right-left (RL)
bf=-2 A bf=2
A bf=0
bf=0 B
B B bf=1
B bf=-1
A bf=0 C bf=0 C bf=0 A bf=0
C bf=0
C bf=0

Left-Left (LL) at A Right-Right (RR) at A

The tree is imbalanced towards the Right side.


To balance this, rotate Left-Left
AVL Trees
• Types of rotations:
– Single rotations: Left-Left (LL), Right-Right (RR)
– Double rotations: Left-Right (LR), Right-left (RL)
bf=-2 A bf=2
A bf=0
bf=0 B
B B bf=1
B bf=-1
A bf=0 C bf=0 C bf=0 A bf=0
C bf=0
C bf=0

Left-Left (LL) at A Right-Right (RR) at A

The tree is imbalanced towards the Right side. The tree is imbalanced towards the Left side.
To balance this, rotate Left-Left To balance this, rotate Right-Right
AVL Trees
• Types of rotations:
– Single rotations: Left-Left (LL), Right-Right (RR)
– Double rotations: Left-Right (LR), Right-left (RL)

A bf=2 A bf=2
bf=0
C
B bf=-1 C bf=1
B bf=0 A bf=0
C bf=0 B bf=0
Left-Left (LL) at B Right-Right (RR) at A

Left-Right rotation at A

The tree is imbalanced towards left and then right. It is corrected by Left-Left rotation
followed by Right-Right rotation
AVL Trees
• Types of rotations:
– Single rotations: Left-Left (LL), Right-Right (RR)
– Double rotations: Left-Right (LR), Right-left (RL)

bf=-2 bf=-2
A A
bf=0
C
B bf=1 C bf=-1
A bf=0 B bf=0
C bf=0 B bf=0

Right-Right(RR) at B Left-Left(LL) at A

Right-Left rotation at A

The tree is imbalanced towards right and then left. It is corrected by Right-Right rotation
followed by Left-Left rotation
AVL Trees
• Example 1:
bf=-1 bf=-2
12 12

3 19 bf=-1 3 19 bf=-2
bf=0 bf=0
Insert 28
22 bf=0 22 bf=-1

28 bf=0

Balanced AVL Un-balanced


tree AVL tree
AVL Trees
• Example 1:
bf=-1 bf=-2
12 12

3 19 bf=-1 3 19 bf=-2
bf=0 bf=0
Insert 28
22 bf=0 22 bf=-1

28 bf=0

Balanced AVL Un-balanced


tree AVL tree

Select the nearest node from the added leaf having the
largest absolute “bf” value. This is node 19.
AVL Trees
• Example 1:
bf=-1 bf=-2
12 12

3 19 bf=-1 3 19 bf=-2
bf=0 bf=0
Insert 28
22 bf=0 22 bf=-1

28 bf=0

Balanced AVL Un-balanced


tree AVL tree

Select the nearest node from the added leaf having the
largest absolute “bf” value. This is node 19.

The imbalance at node 19 is Right-Right


AVL Trees
• Example 1:
bf=-1 bf=-2 bf=-1
12 12 12
bf=0
3 19 bf=-1 3 19 bf=-2 3 22 bf=0
bf=0 bf=0
Insert 28 Left-Left
22 bf=0 22 bf=-1 rotation 19 bf=0 28 bf=0
at 19
28 bf=0

Balanced AVL Un-balanced Balanced AVL


tree AVL tree tree

Select the nearest node from the added leaf having the
largest absolute “bf” value. This is node 19.

The imbalance at node 19 is Right-Right

Correct the tree with Left-Left rotation at 19


AVL Trees
• Example 2:
bf=-1 bf=-2
12 12
bf=0 bf=0
3 22 bf=0 3 22 bf=1
Insert 21
19 bf=0 28 bf=0 19 28 bf=0
bf=-1
21 bf=0
Balanced AVL Un-balanced
tree AVL tree
AVL Trees
• Example 2:
bf=-1 bf=-2
12 12
bf=0 bf=0
3 22 bf=0 3 22 bf=1
Insert 21
19 bf=0 28 bf=0 19 28 bf=0
bf=-1
21 bf=0
Balanced AVL Un-balanced
tree AVL tree

Select the nearest node from the added leaf having the
largest absolute “bf” value. This is node 12.
AVL Trees
• Example 2:
bf=-1 bf=-2
12 12
bf=0 bf=0
3 22 bf=0 3 22 bf=1
Insert 21
19 bf=0 28 bf=0 19 28 bf=0
bf=-1
21 bf=0
Balanced AVL Un-balanced
tree AVL tree

Select the nearest node from the added leaf having the
largest absolute “bf” value. This is node 12.

The imbalance at node 12 is Right-Left


AVL Trees
• Example 2:
bf=-1 bf=-2 bf=-2
12 12 12

bf=0 bf=0 bf=0


3 22 bf=0 3 22 bf=1 3 19 bf=1
Insert 21 Right- bf=0
19 bf=0 28 bf=0 19 28 bf=0 Right 21
bf=-1 rotation
21 bf=0 at 12 bf=0 22 28 bf=0
Balanced AVL Un-balanced
tree AVL tree

19 bf=0
bf=1
12 bf=0
Select the nearest node from the added leaf having the 21
largest absolute “bf” value. This is node 12. bf=0 Left-Left
3 22 bf=0 28 bf=0 rotation
The imbalance at node 12 is Right-Left at 12
Balanced AVL
Correct the tree by performing RL rotation, ie. Right-Right tree
followed by Left-Left at node 12
AVL Trees
• The insertion of a node into an AVL tree is made of two parts
• Finding the parent to which a node needs to be inserted.
– This can be performed in O(lg n) time.
• After a parent is found, insert a leaf node. Correct violations in the AVL balance
factor by performing rotation operations
– The AVL tree satisfies balance factor conditions before the new node is inserted
– Due to this nature, at most 2 rotations would be needed to correct the tree
Agenda
• Introduction to the Tree Data Structure
• Binary Search Trees
• Red-Black Trees
• Adelson-Velskii and Landis (AVL) Trees
• Other structures:
– Trie, Min/Max heap, B-Trees
Other Trees: Trie, Min/Max Heap, B-Trees
• Trie may be used to store heirarchical sequence data
• Min/Max Heaps are a special case of Binary trees
• B-Trees: Similar to Binary trees, but with several hundred children per node

Start/ NULL
A B L E
Head

B E Y NULL

P P L E NULL

B A S E NULL

...... The start node will point to all words beginning


with a specific alphabet

Z O N E NULL
Other Trees: Trie, Min/Max Heap, B-Trees
• Trie may be used to store hierarchical sequence data, Example: dictionaries
– Time taken to search for a word having k alphabets: O(k lg m), where “m” is the number of
unique alphabets in the dictionary (For ASCII upper case m = 26)

Start/ NULL
A B L E
Head

B E Y NULL

P P L E NULL

B A S E NULL

...... The start node will point to all words beginning


with a specific alphabet

Z O N E NULL
Other Trees: Trie, Min/Max Heap, B-Trees
• Min/Max Heaps are a special case of Binary trees
– The parent of each sub-tree is the smallest/largest element of the subtree
– Can be used to store store probability sequences, generate Huffman codes
– Insertion/Delection/Search and other operations take the same time as Binary tree

22

4 19

1 3 16

Existing Max-heap,
generated by inserting
integers: 19, 1, 4, 3,
22, 16
Other Trees: Trie, Min/Max Heap, B-Trees
• Min/Max Heaps are a special case of Binary trees
– The parent of each sub-tree is the smallest/largest element of the subtree
– Can be used to store store probability sequences, generate Huffman codes
– Insertion/Delection/Search and other operations take the same time as Binary tree

22 22

4 19 4 19

1 3 16 Insert 10 1 3 16

10
Existing Max-heap,
generated by inserting Insert 10 at a leaf node by following
integers: 19, 1, 4, 3, BST search conditions. This tree is
22, 16 not a max-heap, correct needs to be
called on node 10
Other Trees: Trie, Min/Max Heap, B-Trees
• Min/Max Heaps are a special case of Binary trees
– The parent of each sub-tree is the smallest/largest element of the subtree
– Can be used to store store probability sequences, generate Huffman codes
– Insertion/Delection/Search and other operations take the same time as Binary tree

22 22 22

4 19 4 19 10 19

1 3 16 Insert 10 1 3 16 Correct 1 4 16
10
10 3
Existing Max-heap,
generated by inserting Insert 10 at a leaf node by following Corrected max-heap tree
integers: 19, 1, 4, 3, BST search conditions. This tree is
22, 16 not a max-heap, correct needs to be
called on node 10
Other Trees: Trie, Min/Max Heap, B-Trees
• B-Trees: Similar to Binary trees, but with several hundred (or more) children per
node
– Used in managing memory paging/HDD caching systems, database entries

1900

100 1000 1800 4000 6000

10 90 1020 1500 1850 8000 9000

120
2020 4800 5600

In this example, height of the tree = 2. Each parent has 2-4 child nodes. Red boxes
indicate the key values and yellow boxes indicate pointers to other nodes
Thank You !!!

You might also like