0% found this document useful (0 votes)
7 views75 pages

Tree

The document provides an overview of trees as hierarchical data structures, detailing their characteristics, types, and traversal methods. It explains binary trees, binary search trees, and AVL trees, including their properties and operations such as insertion, searching, and rotations for balancing. Additionally, it includes code examples for implementing these tree structures in programming.

Uploaded by

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

Tree

The document provides an overview of trees as hierarchical data structures, detailing their characteristics, types, and traversal methods. It explains binary trees, binary search trees, and AVL trees, including their properties and operations such as insertion, searching, and rotations for balancing. Additionally, it includes code examples for implementing these tree structures in programming.

Uploaded by

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

Tree in Data Structure

What are trees?

1. Tree is a hierarchical data structure which stores the information naturally in the form
of hierarchy style.
2. Tree is one of the most powerful and advanced data structures.
3. It is a non-linear data structure compared to arrays, linked lists, stack and queue.
4. It represents the nodes connected by edges.
A is a parent of B and C.
B is called a child of A and also parent of D, E, F.

Tree is a collection of elements called Nodes, where each


node can have arbitrary number of children.
Root  Root is a special node in a tree. The entire tree is
referenced through it. It does not have a parent.

Parent Node Parent node is an immediate predecessor of a


node.

Child Node All immediate successors of a node are its


children.

Siblings Nodes with the same parent are called Siblings.

Path Path is a number of successive edges from source node to


destination node.

Height of Tree  Height of tree represents the height of its root


Levels of a node
Levels of a node represents the number of connections between the node and the
root. It represents generation of a node. If the root node is at level 0, its next
node is at level 1, its grand child is at level 2 and so on. Levels of a node can be
shown as follows:

Note:-
-If node has no children, it is called Leaves or External Nodes.
- Nodes which are not leaves, are called Internal Nodes. Internal nodes have at
least one child.
- A tree can be empty with no nodes or a tree consists of one node called the
Root.
Height of a Node
height of a node is a number of edges on the longest path between that node and a leaf.
Each node has height.

In the above figure, A, B, C, D can have height. Leaf cannot have height as there will be
no path starting from a leaf. Node A's height is the number of edges of the path to K not to
D. And its height is 3.
Note:
- Height of a node defines the longest path from the node to a leaf.
- Path can only be downward.
Binary Tree
"A tree in which every node can have maximum of two children is called as Binary
Tree."
Binary Tree Traversal
Binary tree traversing is a process of accessing every node of the tree and exactly once.
A tree is defined in a recursive manner. Binary tree traversal also defined recursively.

There are three techniques of traversal:

1. Preorder Traversal
2. Postorder Traversal
3. Inorder Traversal
Algorithm for preorder traversal
Step 1 : Start from the Root.

Step 2 : Then, go to the Left Subtree.

Step 3 : Then, go to the Right Subtree.


Step 1 : A + B (B + Preorder on D (D + Preorder on E and F)) + C (C + Preorder on G
and H)

Step 2 : A + B + D (E + F) + C (G + H)

Step 3 : A + B + D + E + F + C + G + H

Preorder Traversal : A B C D E F G H
Algorithm for postorder traversal
Step 1 : Start from the Left Subtree (Last Leaf).

Step 2 : Then, go to the Right Subtree.

Step 3 : Then, go to the Root.


Step 1 : As we know, preorder traversal starts from left subtree (last leaf)
((Postorder on E + Postorder on F) + D + B )) + ((Postorder on G + Postorder on
H) + C) + (Root A)

Step 2 : (E + F) + D + B + (G + H) + C + A

Step 3 : E + F + D + B + G + H + C + A

Postorder Traversal : E F D B G H C A
Algorithm for inorder traversal
Step 1 : Start from the Left Subtree.

Step 2 : Then, visit the Root.

Step 3 : Then, go to the Right Subtree.


Step 1 : B + (Inorder on E) + D + (Inorder on F) + (Root A ) + (Inorder on
G) + C (Inorder on H)

Step 2 : B + (E) + D + (F) + A + G + C + H

Step 3 : B + E + D + F + A + G + C + H

Inorder Traversal : B E D F A G C H
Types of Binary Tree
There are four types of binary tree:

1. Full Binary Tree


2. Complete Binary Tree
3. Skewed Binary Tree
4. Extended Binary Tree
Full Binary Tree
1. If each node of binary tree has either two children or no child at all, is said to be
a Full Binary Tree.
2. Full binary tree is also called as Strictly Binary Tree.
Complete Binary Tree
1. If all levels of tree are completely filled except the last level and the last level has
all keys as left as possible, is said to be a Complete Binary Tree.
2. Complete binary tree is also called as Perfect Binary Tree.
Skewed Binary Tree
1. If a tree which is dominated by left child node or right child node, is said to be a
Skewed Binary Tree.
2. In a skewed binary tree, all nodes except one have only one child node. The remaining
node has no child.
Extended Binary Tree
1. Extended binary tree consists of replacing every null subtree of the original tree with
special nodes.
2. Empty circle represents internal node and filled circle represents external node.
3. The nodes from the original tree are internal nodes and the special nodes are external
nodes.
4. Every internal node in the extended binary tree has exactly two children and every
external node is a leaf. It displays the result which is a complete binary tree.
Binary Tree Representation
Types of Recursion
Binary Tree

#include <stdio.h>
#include <stdlib.h>

typedef struct Node {


int data;
struct Node* left;
struct Node* right;
} Node;

Node* createTree();
void inorder(Node* root);
Binary Tree

int main() {
printf("Create the binary tree:\n");
Node* root = createTree();

printf("Inorder: ");
inorder(root);
printf("\n");

return 0;
}
Binary Tree

Node* createNode(int data) {


Node* newNode = (Node*)malloc(sizeof(Node));
newNode->data = data;
newNode->left = NULL;
newNode->right = NULL;
return newNode;
}
Binary Tree

Node* createTree() {
int data;

printf("Enter data (-1 for no node): ");


scanf("%d", &data);

if (data == -1) {
return NULL;
}

Node* root = createNode(data);


Binary Tree

printf("Enter left for %d:\n", data);


root->left = createTree();

printf("Enter right for %d:\n", data);


root->right = createTree();

return root;
}
Binary Tree

void inorder(Node* root) {


if (root == NULL) {
return;
}

inorder(root->left);

printf("%d ", root->data);

inorder(root->right);
}
Binary Tree Using Array

#include <stdio.h>
#include <stdlib.h>

#define MAX_SIZE 100


#define EMPTY -1

void insert(int tree[], int data, int index);


void inorder(int tree[], int index);
int main() {

int i;

int tree[MAX_SIZE];
for ( i = 0; i < MAX_SIZE; i++) {
tree[i] = EMPTY;
}

insert(tree, 1, 0);
insert(tree, 2, 1);
insert(tree, 3, 2);
insert(tree, 4, 3);
insert(tree, 5, 4);
printf("Inorder Traversal: ");
inorder(tree, 0);
printf("\n");

return 0;
}

void insert(int tree[], int data, int index) {


if (index >= MAX_SIZE) {
printf("Error: Index out of bounds.\n");
return;
}
tree[index] = data;
}
void inorder(int tree[], int index) {
if (index >= MAX_SIZE || tree[index] == EMPTY) {
return;
}

inorder(tree, 2 * index + 1);


printf("%d ", tree[index]);
inorder(tree, 2 * index + 2);
}
What is Binary Search Tree
Binary Search Tree (BST) is a special type of binary tree in which
the left child of a node has a value less than the node’s value and
the right child has a value greater than the node’s value. This
property is called the BST property and it makes it possible to
efficiently search, insert, and delete elements in the tree.

Properties of Binary Search Tree:


1. The left subtree of a node contains only nodes with keys lesser
than the node’s key.
2. The right subtree of a node contains only nodes with keys
greater than the node’s key.
3. The left and right subtree each must also be a binary search
tree.
4. There must be no duplicate nodes(BST may have duplicate
values with different handling approaches).
Basic Operations on Binary Search Tree:
1. Searching a node in BST:

2. First, compare the element to be searched with the root element of the tree.

-> If root is matched with the target element, then return the node’s location.
-> If it is not matched, then check whether the item is less than the root
element, if it is smaller than the root element, then move to the left subtree.
->If it is larger than the root element, then move to the right subtree.

2. Repeat the above procedure recursively until the match is found.

3.If the element is not found or not present in the tree, then return NULL.
Binary Search Tree

#include <stdio.h>
#include <stdlib.h>

struct Node {
int data;
struct Node* leftChild;
struct Node* rightChild;
};
Binary Search Tree

struct Node* createNode(int data) {


struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
newNode->data = data;
newNode->leftChild = NULL;
newNode->rightChild = NULL;
return newNode;
}
Binary Search Tree

struct Node* insert(struct Node* root, int data) {


if (root == NULL) {
return createNode(data);
}

if (data < root->data) {


root->leftChild = insert(root->leftChild, data);
} else if (data > root->data) {
root->rightChild = insert(root->rightChild, data);
}

return root;
}
Binary Search Tree

struct Node* search(struct Node* root, int data) {


if (root == NULL || root->data == data) {
return root;
}

if (data < root->data) {


return search(root->leftChild, data);
}

return search(root->rightChild, data);


}
Binary Search Tree

void inorder(struct Node* root) {


if (root != NULL) {
inorder(root->leftChild);
printf(" --%d", root->data);
inorder(root->rightChild);
}
}

void postorder(struct Node* root) {


if (root != NULL) {
postorder(root->leftChild);
postorder(root->rightChild);
printf(" --%d", root->data);
}
}
Binary Search Tree

void preorder(struct Node* root) {


if (root != NULL) {
printf(" --%d", root->data);
preorder(root->leftChild);
preorder(root->rightChild);
}
}
Binary Search Tree

int main() {
struct Node* root = NULL;
int choice, data;

do {
printf("\n1. Insert\n2. Inorder\n3. Postorder\n4. Preorder\n5. Search\n6.
Exit\n");
printf("Enter your choice: ");
scanf("%d", &choice);

switch (choice) {
case 1:
printf("Enter Value: ");
scanf("%d", &data);
root = insert(root, data);
break;
Binary Search Tree

case 2:
inorder(root);
printf("\n");
break;

case 3:
postorder(root);
printf("\n");
break;

case 4:
preorder(root);
printf("\n");
break;
Binary Search Tree
case 5:
printf("Enter Value to Search: ");
scanf("%d", &data);
struct Node* result = search(root, data);
if (result != NULL) {
printf("Element %d found\n", data);
} else {
printf("Element not found\n");
}
break;
}
} while (choice != 6);

return 0;
}
AVL Tree

AVL Tree is invented by GM Adelson - Velsky and EM Landis in


1962. The tree is named AVL in honour of its inventors.

AVL Tree can be defined as height balanced binary search tree


in which each node is associated with a balance factor which is
calculated by subtracting the height of its right sub-tree from
that of its left sub-tree.

Tree is said to be balanced if balance factor of each node is in


between -1 to 1, otherwise, the tree will be unbalanced and need
to be balanced.

Balance Factor (k) = height (left(k)) - height


(right(k))
AVL Rotations

We perform rotation in AVL tree only in case if Balance Factor is other


than -1, 0, and 1. There are basically four types of rotations which are
as follows:

1. L L rotation: Inserted node is in the left subtree of left subtree of A.

2. R R rotation : Inserted node is in the right subtree of right subtree of


A.

3. L R rotation : Inserted node is in the right subtree of left subtree of


A.

4. R L rotation : Inserted node is in the left subtree of right subtree of


A.
RR Rotation
When BST becomes unbalanced, due to a node is inserted into the right subtree of
the right subtree of A, then we perform RR rotation, RR rotation is an
anticlockwise rotation, which is applied on the edge below a node having balance
factor -2.
LL Rotation
When BST becomes unbalanced, due to a node is inserted into the left subtree of
the left subtree of C, then we perform LL rotation, LL rotation is clockwise
rotation, which is applied on the edge below a node having balance factor 2.
LR Rotation
Double rotations are bit tougher than single rotation which has already explained
above. LR rotation = RR rotation + LL rotation, i.e., first RR rotation is
performed on subtree and then LL rotation is performed on full tree, by full tree
we mean the first node from the path of inserted node whose balance factor is
other than -1, 0, or 1.

A node B has been inserted into the right subtree of A the left
subtree of C, because of which C has become an unbalanced node
having balance factor 2. This case is L R rotation where: Inserted
node is in the right subtree of left subtree of C
As LR rotation = RR + LL rotation, hence RR (anticlockwise) on
subtree rooted at A is performed first. By doing RR rotation, node A,
has become the left subtree of B.

After performing RR rotation, node C is still unbalanced, i.e.,


having balance factor 2, as inserted node A is in the left of left of
C
Now we perform LL clockwise rotation on full tree, i.e. on node
C. node C has now become the right subtree of node B, A is left
subtree of B

Balance factor of each node is now either -1, 0, or 1, i.e.


BST is balanced now.
RL Rotation

R L rotation = LL rotation + RR rotation, i.e., first LL rotation is performed on


subtree and then RR rotation is performed on full tree, by full tree we mean the
first node from the path of inserted node whose balance factor is other than -1, 0,
or 1.

A node B has been inserted into the left subtree of C the right
subtree of A, because of which A has become an unbalanced node
having balance factor - 2. This case is RL rotation where: Inserted
node is in the left subtree of right subtree of A
As RL rotation = LL rotation + RR rotation, hence, LL (clockwise)
on subtree rooted at C is performed first. By doing RR rotation,
node C has become the right subtree of B.

After performing LL rotation, node A is still unbalanced, i.e.


having balance factor -2, which is because of the right-subtree of
the right-subtree node A.
Now we perform RR rotation (anticlockwise rotation) on full tree,
i.e. on node A. node C has now become the right subtree of node B,
and node A has become the left subtree of B.

Balance factor of each node is now either -1, 0, or 1, i.e.,


BST is balanced now.
AVL Tree Implementaion
#include <stdio.h>
#include <stdlib.h>

typedef struct Node {


int data;
int height;
struct Node* left;
struct Node* right;
} Node;

int height(Node* N) {
if (N == NULL)
return 0;
return N->height;
}
int max(int a, int b) {
return (a > b) ? a : b;
}

Node* createNode(int data) {


Node* node = (Node*)malloc(sizeof(Node));
node->data = data;
node->height = 1; // Initial height is set to 1
node->left = NULL;
node->right = NULL;
return node;
}
Node* rightRotate(Node* y) {
Node* x = y->left;
Node* T2 = x->right;

x->right = y;
y->left = T2;

y->height = max(height(y->left), height(y->right)) + 1;


x->height = max(height(x->left), height(x->right)) + 1;

return x;
}
Node* leftRotate(Node* x) {
Node* y = x->right;
Node* T2 = y->left;

y->left = x;
x->right = T2;

x->height = max(height(x->left), height(x->right))


+ 1;
y->height = max(height(y->left), height(y->right))
+ 1;

return y;
}
int getBalance(Node* N) {
if (N == NULL)
return 0;
return height(N->left) - height(N->right);
}
Node* insert(Node* node, int data) {

if (node == NULL)
return createNode(data);

if (data < node->data)


node->left = insert(node->left, data);
else if (data > node->data)
node->right = insert(node->right, data);
else
return node;

node->height = 1 + max(height(node->left), height(node->right));

int balance = getBalance(node);


// Left Left Case
if (balance > 1 && data < node->left->data)
return rightRotate(node);

// Right Right Case


if (balance < -1 && data > node->right->data)
return leftRotate(node);

// Left Right Case


if (balance > 1 && data > node->left->data) {
node->left = leftRotate(node->left);
return rightRotate(node);
}
// Right Left Case
if (balance < -1 && data < node->right->data) {
node->right = rightRotate(node->right);
return leftRotate(node);
}

// Return the (unchanged) node pointer


return node;
}
void inorder(Node* root) {
if (root != NULL) {
inorder(root->left);
printf("%d ", root->data);
inorder(root->right);
}
}

void preorder(Node* root) {


if (root != NULL) {
printf("%d ", root->data);
preorder(root->left);
preorder(root->right);
}
}
void postorder(Node* root) {
if (root != NULL) {
postorder(root->left);
postorder(root->right);
printf("%d ", root->data);
}
}
int main() {
Node* root = NULL;
int choice, value;

do {
printf("\n1. Insert\n2. Inorder\n3. Preorder\n4.
Postorder\n5. Exit\n");
printf("Enter your choice: ");
scanf("%d", &choice);

switch (choice) {
case 1:
printf("Enter value to insert: ");
scanf("%d", &value);
root = insert(root, value);
break;
case 2:
printf("Inorder traversal:\n");
inorder(root);
printf("\n");
break;

case 3:
printf("Preorder traversal:\n");
preorder(root);
printf("\n");
break;
case 4:
printf("Postorder traversal:\n");
postorder(root);
printf("\n");
break;
}
} while (choice != 5);

return 0;
}
Thank You

You might also like