0% found this document useful (0 votes)
0 views

module-4 DS

The document provides an overview of binary trees, including their structure, properties, and types such as strictly binary and complete binary trees. It outlines methods for binary tree storage, insertion, traversal, and searching for keys, along with examples of code implementations. Additionally, it introduces binary search trees (BST) and their unique properties regarding node values in relation to their subtrees.

Uploaded by

Vishwa naykodi
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)
0 views

module-4 DS

The document provides an overview of binary trees, including their structure, properties, and types such as strictly binary and complete binary trees. It outlines methods for binary tree storage, insertion, traversal, and searching for keys, along with examples of code implementations. Additionally, it introduces binary search trees (BST) and their unique properties regarding node values in relation to their subtrees.

Uploaded by

Vishwa naykodi
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/ 40

MODULE-4

TREES
Binary Trees
 A binary tree is a non-linear data structure consisting of nodes
connected by branches (pointers).
 Each node has:
o llink: Address of the left subtree.
o info: Data stored in the node.
o rlink: Address of the right subtree.
 A binary tree can be:
o Empty (no nodes).
o Non-empty, partitioned into:
 1 NODE: First node of the tree.
 2 NODE: Tree with 1 subtree.
 3 NODE: Tree with 2 subtrees.
Key Properties

Binary trees allow at most two subtrees per


node (0, 1, or 2) (REFER FIG 10.2.)
• Invalid cases (not binary trees):
• A node with >2 subtrees (Fig 10.3a).
• Cycles in the tree (Fig 10.3b).
• A subtree pointing back to its ancestor (Fig 10.3c)
Terminology (Fig 10.4)
• Root Node: Topmost node (indegree = 0).
• Child/Son: Nodes directly below a parent.
• Siblings: Nodes sharing the same parent.
• Ancestors: Nodes along the path from the root to a
given node.
• Descendants: Nodes reachable below a given node.
• Left/Right Descendants: Nodes in the left/right
subtree of a node.
• Leaf/External Node: Node with no children (outdegree
= 0).
• Internal Node: Non-leaf node (has at least one child).
• Level: Distance from the root (root = level 0).
• Height/Depth: Maximum level in the tree.
• 50 and 60 are children of
100
• 80 and 40 are children of 60
• 70 is child of 50
• 35 and 30 are children of 80
Types of Binary Trees
Types of Binary Trees
• Strictly Binary Tree: Every node has 0 or 2 children.
• Complete Binary Tree: All levels are fully filled except
possibly the last.
• Almost Complete Binary Tree: Filled left to right but
may not be fully complete.
Strictly Binary Tree
• Definition: Every node has either 0 or 2 children (no
node with only 1 child).
• Examples:
• Fig 10.5.b & 10.5.c: Strictly binary (all nodes have 0 or 2
children).
• Fig 10.5.a: Not strictly binary (node has only 1 child).
Binary Tree Storage
Representation
1. Binary Tree - Linked Allocation 2. Add Left Child:
• 1. Node Structure root->left = (struct node*) malloc(sizeof(struct
node));
struct node { root->left->data = 20;
int data; // Stores the value root->left->left = NULL;
struct node* left; // Pointer to left child root->left->right = NULL;
struct node* right; // Pointer to right Add Right Child:
child root->right = (struct node*)malloc(sizeof(struct
}; node));
root->right->data = 30;
2. Root Pointer
root->right->left = NULL;
struct node* root = NULL; // Empty tree
when NULL root->right->right = NULL;
Key Points
3. How It Works
 Each node has data + 2 pointers (left & right
1.Create Root Node:
children).
root = (struct node*)malloc(sizeof(struct
 root = NULL means empty tree.
node));
 Use malloc() to create nodes, set children
root->data = 10;
to NULL initially. Free() for deallocation
root->left = NULL; // No left child yet
• This is the dynamic way to build a binary tree, similar
root->right = NULL; // No right child yet to linked lists but with two connections per node.
•Array: Fixed size, faster access (parent/child
2. Sequential Allocation via index arithmetic).
(Array) •Fig 10.8: Shows array representation with
numbered nodes (0=A, 1=B, etc.).
 Index Rules (Fig 10.8):
 Parent of D (index 3): (3-1)/2 = 1 (B)
o Root at index 0.  Left child of B (index 1): 2*1 + 1 = 3 (D)
o For any node at index i: Why Use Array?
 Efficient for complete/almost
 Left child: 2i + 1
complete trees (no wasted space).
 Right child: 2i + 2  Disadvantage: Sparse trees waste
 Parent: (i-1)/2 (floor memory.
Refer to Fig 10.8 for visual array indexing.
division).
 Methods:

1.Flag Field Method:


2.Zero-Initialization
Various operations on
binary trees using linked
representation
• Binary Tree Insertion
Insertion Logic
• Goal: Add new nodes to the first available spot (left to
right).
• Rules:
• If tree is empty → new node becomes root.
• Else, insert left if empty.
• If left occupied → insert right.
#include <stdio.h> // Insert a node
#include <stdlib.h> struct Node* insert(struct Node* root,
struct Node { int value) {
int data; if (root == NULL) {
struct Node* left; return createNode(value); //
struct Node* right; Case 1: Empty tree
}; }
// Create a new node if (root->left == NULL) {
struct Node* createNode(int value) root->left = createNode(value);
{ // Case 2: Insert left
struct Node* newNode = (struct } else {
Node*)malloc(sizeof(struct Node)); root->right =
newNode->data = value; createNode(value); // Case 3: Insert
right
newNode->left = newNode-
>right = NULL; }
return newNode; } return root; }
// Print tree (pre-order) int main() {
void printTree(struct Node* struct Node* root = NULL;
root) {
root = insert(root, 10); //
if (root == NULL) return;
Root
printf("%d ", root->data);
printTree(root->left); insert(root, 5); // Left
printTree(root->right); child
} insert(root, 20); //
Right child

printf("Tree: ");
// Build this
tree: printTree(root); // Output:
// 10 10 5 20
// / \
// 5 20 return 0;
}
Binary Tree Insertion
(Based on Direction String - e.g., "LRL")

Insertion Logic
 Goal: Insert a new node at a specific path (e.g., "LRL" = Left → Right
→ Left from root).
 Steps:

1.Start at root.
2.Follow the direction string (e.g., 'L' = move left, 'R' = move right).
3.Insert the new node at the end of the path if the spot is empty
(NULL).
#include <stdio.h> // Traverse the path
#include <stdlib.h> int i;
for (i = 0; i < strlen(direction); i++) {
#include <string.h>
if (cur == NULL) break; // Path
#include <ctype.h> // For toupper() doesn't exist
struct node { prev = cur;
int data; if (toupper(direction[i]) == 'L')
struct node* left; cur = cur->left;
struct node* right; else
}; cur = cur->right;
// Function to insert a node based on directions (e.g., }
"LRL") // Check if insertion is possible
if (cur != NULL || i != strlen(direction))
struct node* insert(struct node* root, int item, char*
{
direction) { printf("Insertion failed: Invalid path
// Create new node or spot occupied.\n");
struct node* temp = (struct free(temp);
node*)malloc(sizeof(struct node)); return root;
temp->data = item; }
temp->left = temp->right = NULL; // Insert the node
// Case 1: Empty tree if (toupper(direction[i-1]) == 'L')
if (root == NULL) return temp; prev->left = temp;
else
// Case 2: Non-empty tree
prev->right = temp;
struct node* prev = NULL;
int main() {
// Create initial tree
struct node* root = NULL;
root = (struct
node*)malloc(sizeof(struct node));
root->data = 10;
root->left = root->right = NULL;

// Insert nodes using directions


root = insert(root, 20, "L"); // Left
of root
root = insert(root, 30, "R"); //
Right of root
root = insert(root, 40, "LL"); // Left
of left child

return 0;
Binary Tree Traversal
Binary Tree Traversal
• Traversal refers to visiting all nodes of a tree
systematically.
• There are three main types, differing in when we
process the root node:
The pre order traversal
void preOrder(struct node*
Definition: The pre order traversal of root) {
a binary tree can be recursively
defined as if (root == NULL) return;
follows: printf("%d ", root-
1. Process the root Node >data); // Process root first
2. Traverse the Left subtree in preOrder(root->left); //
preorder Then left subtree
3. Traverse the Right subtree in preOrder(root->right); //
preorder Finally right subtree
}
Output for our tree
(10,20,40,30):
The inorder traversal
The inorder traversalof a binary
tree can be recursively void inOrder(struct node* root)
defined as follows: {
1. Traverse the Left subtree in if (root == NULL) return;
inorder
2. Process the root Node
inOrder(root->left); //
First left subtree
3. Traverse the Right subtree in
inorder printf("%d ", root->data); //
Then root
inOrder(root->right); //
Finally right subtree
}
Output: 40 20 10 30
The postorder traversal
The postorder traversal of a
binary tree can be recursively void postOrder(struct node*
defined as follows: root) {
1. Traverse the Left subtree in if (root == NULL) return;
postorder [L] postOrder(root->left); //
2. Traverse the Right subtree in First left subtree
postorder [R]
postOrder(root->right); //
3. Process the root Node [N] Then right subtree
printf("%d ", root->data); //
Finally root
}
Searching for a Key in a
Binary Tree
• Binary Tree
Search involves looking struct Node* preorderSearch(struct Node*
for a specific value (key) in root, int key) {
the tree if (root == NULL) return NULL;
• The approach and program if (root->data == key) return root;
to search for an item using
preorder is shown below:
struct Node* left = preorderSearch(root-
Search Approach: >left, key);
• Check if current node if (left != NULL) return left;
matches the key
• If not, search left subtree return preorderSearch(root->right, key);
• Then search right subtree }
Inorder search (Left →
Root → Right)
struct Node* inorderSearch(struct
• Process: Visit left Node* root, int key) {
subtree first, then if (root == NULL) return NULL;
root, then right
subtree
• Search Approach: struct Node* left =
• Search left subtree inorderSearch(root->left, key);
first if (left != NULL) return left;
• Check current node
if (root->data == key) return
• Then search right
subtree root;

return inorderSearch(root-
>right, key);
}
struct Node* postorderSearch(struct
Node* root, int key) {
if (root == NULL) return NULL;
Postorder search
struct Node* left =
(Left → Right → Root) postorderSearch(root->left, key);
• Process: Visit left if (left != NULL) return left;
subtree, then right
subtree, then root struct Node* right =
• Search Approach: postorderSearch(root->right, key);
• Search left subtree if (right != NULL) return right;
first
• Then search right if (root->data == key) return root;
subtree
• Finally check current
node return NULL;
}
Copying a Binary Tree
Operation
Copying a Binary Tree Operation
• Copying a binary tree involves creating an exact
duplicate of the original tree while maintaining its
structure.
• This can be done using different traversal methods
(preorder, inorder, postorder), but postorder
traversal is commonly used for deletion,
while preorder traversal is natural for copying.
// Function to copy a binary tree
(recursive preorder)

struct Node* copyTree(struct Node*


root) {
……
if (root == NULL) {
temp->data = root->data;
return NULL; }
// Recursively copy left
// Create a new node and copy data and right subtrees
struct Node* temp = (struct temp->left =
Node*)malloc(sizeof(struct Node)); copyTree(root->left);
if (temp == NULL) { temp->right =
fprintf(stderr, "Memory allocation
copyTree(root->right);
failed!"); return temp; }
Binary Search Tree
(BST)
A Binary Search Tree (BST) is a binary tree where:
• Left subtree of a node contains values less than the node’s value.
• Right subtree contains values greater than or equal to the node’s
value.
• Every node in the tree should satisfy this condition, if leftsubtree
or right subtree exists.
• Example:
Key Operations
struct Node* insert(int item, struct Node*
root) {
if (root == NULL) {
Insertion struct Node* newNode = (struct
Node*)malloc(sizeof(struct Node));
Goal:
node Add a
while new newNode->info = item;
maintaining
properties. BST NULL;
newNode->lptr = newNode->rptr =

Steps: return newNode;


Start
1.the from
root.
}
if (item < root->info)
Traverse
2.new value left
< if root->lptr = insert(item, root->lptr); //
current
else node,
traverse
Left subtree
else
right. root->rptr = insert(item, root->rptr); //
Insert at
3.correct the
empty
Right subtree
return root;
spot. }

You might also like