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

Data Structures

The document provides an overview of data structures, including arrays, stacks, queues, and their classifications into primitive and non-primitive types. It discusses major operations like searching, sorting, insertion, updating, and deletion, along with the advantages of using data structures. Additionally, it covers linear and non-linear data structures, memory representation, and sparse matrices, detailing their representations and applications.

Uploaded by

hgsju8559
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)
11 views

Data Structures

The document provides an overview of data structures, including arrays, stacks, queues, and their classifications into primitive and non-primitive types. It discusses major operations like searching, sorting, insertion, updating, and deletion, along with the advantages of using data structures. Additionally, it covers linear and non-linear data structures, memory representation, and sparse matrices, detailing their representations and applications.

Uploaded by

hgsju8559
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/ 213

DATA STRUCTURES

UNIT-I
UNIT I
Introduction to Data Structure:
 Arrays - Fundamentals, Representations, and Applications,
 Sparse Matrices.
 Stacks - Operations on stacks, Applications - Infix to postfix conversion,
evaluation of postfix expressions, Tower of Hanoi.
 Queues - Operations and applications, Types - Circular Queue, Priority
Queue.
INTRODUCTION TO DATA STRUCTURES
Data Structure is a way of collecting and organizing data in such a
way that we can perform operations on these data in an effective way.
Ex:- Assume student’s name “Rohit" and age 20. Here “Rohit" is
of String data type and 20 is of integer data type.

We can organize this data as a record like Student record, which will
have both student's name and age in it. Now we can collect and store
student’s records in a file or database as a data structure.
Classifications of Data Structures
Data Structures are classified into two categories:

1.Primitive Data Structure


 These data structures consisting of the numbers and the
characters that come in-built into programs.
 Basic data types like Integer, Float, Character,
and Boolean come under the Primitive Data Structures.
 These data types are also called Simple data types, as they
contain characters
2.Non-Primitive Data Structures
 Non-Primitive Data Structures are those data structures
derived from Primitive Data Structures.
 The focus of these data structures is on forming a set of data
elements that is either homogeneous(same datatype)
or heterogeneous (different data types).
 Based on the structure and arrangement of data, we can
divide these data structures into two sub-categories -
1.Linear Data Structures
2.Non-Linear Data Structures
Major Operations
The major or the common operations that can be performed on the data
structures are:
•Searching: We can search for any element in a data structure.
•Sorting: We can sort the elements of a data structure either in an
ascending or descending order.
•Insertion: We can also insert the new element in a data structure.
•Updation: We can also update the element, i.e., we can replace the
element with another element.
•Deletion: We can also perform the delete operation to remove the
element from the data structure
Advantages of Data structures

•Efficiency: If the choice of a data structure for implementing a particular ADT


is proper, it makes the program very efficient in terms of time and space.
•Reusability: The data structure provides reusability means that multiple client
programs can use the data structure.
•Abstraction: The data structure specified by an ADT also provides the level
of abstraction. The client cannot see the internal working of the data structure,
so it does not have to worry about the implementation part. The client can only
see the interface.
LINEAR DATA STRUCTURE:-
If a data structure organizes the data in sequential order, then that data structure
is called a Linear Data Structure. The arrangement of the data is done linearly,
where each element consists of the successors and predecessors except the first
and the last data element.
Based on memory allocation, the Linear Data Structures are further classified
into two types:
Static Data Structures: The data structures having a fixed size are known as
Static Data Structures. The memory for these data structures is allocated at the
compiler time, and their size cannot be changed
Ex:- ARRAY
Dynamic Data Structures: The data structures having a dynamic size are
known as Dynamic Data Structures. The memory of these data structures is
allocated at the run time
Ex:-Linked Lists, Stacks, and Queues.
Non-Linear Data Structures
 Non-Linear Data Structures are data structures where the data
elements are not arranged in sequential order.
 Here, the insertion and removal of data are not feasible in a linear
manner.
 There exists a hierarchical relationship between the individual data
items.
Ex:- Trees,Graphs
Arrays
Fundamentals, Representations, & Applications
Array:
An array is defined as the collection
of similar type of data items stored
at contiguous memory locations.

Representation of an array
We can represent an array in various ways in different programming languages.
Declaration of Array:-
1.data_type array_name[array_size];
Ex:-int marks[5]

Initialization of Array
The simplest way to initialize an array is by
using the index of each element. We can
initialize each element of the array by using the
index.
Consider the following example.
2.marks[0]=80;//initialization of array
2.marks[1]=60;
3.marks[2]=70;
4.marks[3]=85;
5.marks[4]=75;
Characteristics of Arrays in Data Structures
Fixed Size: Once an array is declared, its size cannot be changed.
Homogeneous Elements: All elements in an array must be of the same data
type, such as all integers, all floats, or all characters.
Indexed by Integers: Each element in an array is assigned a unique integer
called an index, which identifies its position within the array. Indexing usually
starts at 0.
Efficient Access: Because of the way arrays are stored in memory
(contiguously), accessing any element by its index is very efficient. This
direct access using the index is often referred to as "random access."
Advantages
1) Code Optimization: Less code to the access the data.
2) Ease of traversing: By using the for loop, we can retrieve the
elements of an array easily.
3) Ease of sorting: To sort the elements of the array, we need a few
lines of code only.
4) Random Access: We can access any element randomly using the
array.
Disadvantages
1) Fixed Size: Whatever size, we define at the time of declaration of
the array, we can't exceed the limit.
Applications of Array:
1.We can store a list of data elements belonging to the same data type.
2.Array acts as an auxiliary storage for other data structures.
3.The array also helps store data elements of a binary tree of the fixed
count.
4.Array also acts as a storage of matrices.
Types of Arrays
An array in C is a collection of elements of the same data type, stored in
contiguous memory locations. There are two types of arrays:
● One Dimensional Array
● Two Dimensional Array

One Dimensional Array


A one-dimensional (1D) array is a linear list of elements of the same data type,
such as integers or characters. The elements are stored in contiguous memory
locations and can be accessed using a single index. The index of the elements in
a 1D array starts from 0.
Two Dimensional Array
A two-dimensional (2D) array is a table-like structure that stores data in rows and
columns. The elements are stored in contiguous memory locations and can be accessed
using two indices, one for the row and one for the column. The index of the elements in a
2D array starts from 0.
Memory Representation of Array
The most common way to
represent an array in memory is to
store the elements sequentially in a
block of memory.
For example, if we have an array
of integers a with 5 elements, the
memory representation would look
like this:
Row Major Order & Column Major Order
There are two main ways to represent an array in memory: row-major order and column-major
order.
Row Major Order
In row-major order, the elements of the array are stored row by row in memory. For example,
in a two-dimensional array A[i][j], the elements of the first row are stored first, followed by
the elements of the second row, and so on. Within each row, the elements are stored in order of
increasing column index. This means that the memory location of an element A[i][j] can be
computed as &A[0][0] + i * n + j, where n is the number of columns in the array.
Column Major Order
In column-major order, the elements of the array are stored column by
column in memory. For example, in a two-dimensional array A[i][j], the
elements of the first column are stored first, followed by the elements of the
second column, and so on. Within each column, the elements are stored in
order of increasing row index. This means that the memory location of an
element A[i][j] can be computed as &A[0][0] + j * m + i, where m is the
number of rows in the array.
Address Calculation in One Dimensional Array
To access an element in an array, the computer needs to know its memory address. The
memory address of an array element can be calculated using the following formula:
address = base_address + index * size_of_element
Where:
● base_address: the memory address of the first element in the array.
● index: the index or subscript of the element you want to access.
● size_of_element: the size (in bytes) of each element in the array.

For example, let's say you have an array of integers with 5 elements and the base address
of the array is 100. The size of each integer element is 4 bytes. To access the third
element a[2] of the array, you would use the following formula:
a[2] = 100 + 2 * 4 = 108
Address Calculation in Two Dimensional Array
To access an element in a 2D array, the computer needs to know its memory address. The
memory address of an element in a 2D array can be calculated using the following formula:
address = base_address + (row_index * num_columns + column_index) * size_of_element
Where:
● base_address: the memory address of the first element in the 2D array.
● row_index: the index of the row containing the element you want to access.
● column_index: the index of the column containing the element you want to access.
● num_columns: the number of columns in the 2D array.
● size_of_element: the size (in bytes) of each element in the 2D array.

For example, let's say you have a 2D array of integers with 3 rows and 4 columns, and the
base address of the array is 100. The size of each integer element is 4 bytes. To access the
element at row 1, column 0 which is a[1][0] you would use the following formula:
a[1][0] = 100 + (1 * 4 + 0) * 4 = 116
Basic operations
Traversal - This operation is used to print the elements of the array.
Insertion - It is used to add an element at a particular index.
Deletion - It is used to delete an element from a particular index.
Search - It is used to search an element using the given index or by the
value.
Update - It updates an element at a particular index.
Traversal Operation
Array traversal refers to the process of accessing each element of an array in a
sequential order.
Algorithm for Traversing an Array
Traversal (data,LB,UB)
Here data is array name and LB is Lower Bound (start) index of the first element of
an array. UB is Upper Bound (End) is the index of the last element

Step 1: Start
Step 2: [Initialize variable. ] Set i = LB
Step 3: Repeat steps 4 and 5 While i <= UB
Step 4: Apply process (Print ) to data[i].
Step 5: Increment i=i+1
Step 6: End of loop
Step 7: Stop
Insertion Operation
Insertion in an array refers to the process of adding a new element to a specific position
within the array

Algorithm to Insert an element in an Array


Here size is the array size. Position (pos) is location where element to be inserted and Item
is new value in the array

Step 1: Start
Step 2: [Initialize variable ] Set i = size - 1
Step 3: Repeat Step 4 and 5 While i >= pos-1
Step 4: [Move ith element forward. ] set arr[i+1] = arr[i]
Step 5: [Decrease counter. ] Set i = i - 1
Step 6: [End of step 3 loop. ]
Step 7: [Insert element. ] Set arr[pos-1] = item
Step 8: Stop
Deletion Operation
Deletion in an array means removing an element from an array
Algorithm to Delete an element from an Array:
Step 1: Start
Step 2: [Initialize variable] Set i = pos - 1
Step 3: Repeat Step 4 and 5 for i = pos - 1 to i < size
Step 4: [Move ith element left side ] set a[i] = a[i+1]
Step 5: [Incerement ] Set i = i + 1
Step 6: [End of step 03 loop. ]
Step 7: [Update Array Size] set size = size - 1
Step 8: Stop
SPARSE MATRICES
Sparse Matrix:-
 A sparse matrix is a matrix that
contains a large number of zero
elements compared to non-zero
elements.
 In such matrices, it is not efficient to
use traditional representations, which
store all elements, because a
significant amount of memory will
be wasted on storing zero elements.
 Therefore, special techniques are
used to represent sparse matrices,
which can save a lot of memory.
Representation of Sparse Matirx
Sparse matrices can be represented using both arrays and linked lists.

1.Array Representation: We use Two-dimensional arrays to store the non-


zero elements of the sparse matrix. In 2D array representation of sparse
matrix, there are three fields used that are named as -
ROW,COLUMN,VALUE.

2.Linked List Representation: We use a linked list to store the non-zero


elements of the sparse matrix. Each node of the linked list represents a non-
zero element and contains three fields: the value of the element, the row
index of the element, the column index of the element and next node to
store the address of next node.
Array Representation of Sparse Matrix
In the array representation of a sparse matrix, we store only the non-zero
elements of the matrix along with their row and column indices.
We use three arrays to represent the sparse matrix:
1.row_index: It stores the row indices of the corresponding elements in the array.
2.col_index:It stores the column indices of the corresponding elements in the
array.
3.value : It stores the non-zero elements of the matrix in row-major order.
The size of these arrays depends on the number of non-zero elements in the
matrix.
Program in C to implement array representation of sparse matrix

#include <stdio.h>
int main(){
int sm[100][100], rows, cols, i, j, nonzero = 0;
printf("Enter no of rows & columns of the matrix: ");
scanf("%d %d", &rows, &cols);
printf("Enter the matrix elements:");
for (i = 0; i < rows; i++){
for (j = 0; j < cols; j++){
scanf("%d", &sm[i][j]);
if (sm[i][j] != 0){
nonzero++;
}}}
int fmatrix[3][nonzero];
int k=0;
for(int i=0; i<rows; i++) { OUTPUT:-
for(int j=0; j<cols; j++) { Enter no of rows & columns of the matrix:
if(sm[i][j]!=0) { 3
fmatrix[0][k] = i; 4
fmatrix[1][k] = j; Enter the matrix elements:
fmatrix[2][k] = sm[i][j]; 4
k++; 0
} } } 0
for(int i=0 ;i<rows; i++) { 3
for(int j=0; j<cols; j++) { 0
printf("%d ", fmatrix[i][j]); 2
} } } 0
0
6
1
0
0
001203104326
Linked List Representation of Sparse Matrix

 A linked list representation of a sparse matrix is a way of storing a matrix


that has a large number of zero values efficiently by using linked lists.

 Each node in the linked list contains the value of the non-zero element,
its column index, row index, and a pointer to the next node in the list.

 This representation reduces the amount of memory required to store the


matrix and allows for efficient manipulation of the non-zero elements.

 The benefit of using a linked list instead of an array to represent the


sparse matrix is that it is simpler to add or remove nodes from a linked
list than from an array.
 Row - Row where the non-zero element is located.
 Column - Column where the non-zero element is located.
 Value - It is the value of the non-zero element that is located at the index (row,
column).
 Next node - Address of the next node.
STACKS
Operations on stacks,
Applications - Infix to postfix conversion,
evaluation of postfix expressions
Stack
❖ A stack is a linear data structure that follows
the Last-In-First-Out (LIFO) principle, where the
element that is inserted last will be the first to be
removed.
❖ A stack has one end, typically called the top.The top
of the stack is the element that was most recently
added, and the bottom of the stack is the element that
was added first or the earliest.
❖ The top of the stack is represented using a pointer,
called the top pointer, which points to the last
element inserted. When a new element is added to the
stack, it is placed on the top of the stack, and the top
pointer is updated to point to the new element.
Memory Representation of Stack
A stack can be implemented using an array or a
linked list. In both cases, memory is used to store the
stack elements and manage the stack operations.

Memory Representation of Stack using Arrays: In


an array-based stack, the stack elements are stored in
a contiguous block of memory, typically an array.
The stack pointer points to the topmost element of
the stack, and the stack operations modify the stack
pointer and the elements in the array. When the stack
size is fixed, the array-based stack can overflow or
underflow, causing memory access errors.
Memory Representation of Stack using Linked List:

 In a linked list-based stack, the stack elements are stored in individual


nodes, each with a pointer to the next node.
 The stack pointer points to the head node of the linked list, and the stack
operations modify the stack pointer and the links between the nodes.
 When the stack size is dynamic, the linked list-based stack can allocate or
deallocate memory as needed, avoiding overflow or underflow errors.
BASIC STACK OPERATIONS
Push Operation: Inserts a new element 'item' onto the top of the stack.
However, attempting a push will result in an overflow error condition if the
stack is already at its maximum capacity.
1.Check if the stack is full (top == size - 1)
2.If full, return an error (stack overflow)
3.If not full, increment 'top' and insert the new element at the new 'top'
index
Pop Operation:Removes and returns the topmost element from the stack. But if
the stack is empty, attempting a pop will trigger an underflow error, as there are
no elements to remove.
4.Check if the stack is empty (top == -1)
5.If empty, return an error (stack underflow)
6.If not empty, retrieve the element at the 'top' index
7.Decrement 'top' to remove the topmost element
Peek Operation:Retrieves the value of the topmost element without removing
it from the stack. If the stack is empty, it indicates an error state.
1.Check if the stack is empty (top == -1)
2.If empty, return an error
3.If not empty, return the element at the 'top' index (without removing
it)
isEmpty Operation:Checks if the stack is empty by verifying if the top pointer
points to a sentinel value (e.g., -1). Returns true if the stack is empty; otherwise,
it is false.
4.Check if 'top' is equal to -1
5.If yes, return true (stack is empty)
6.If no, return false (stack is not empty)
isFull Operation:isFull(): Determines if the stack has reached its maximum
capacity by checking if the top pointer is at the last valid index. Returns true if full,
false if not.
1.Check if 'top' is equal to size - 1
2.If yes, return true (stack is full)
3.If no, return false (stack is not full)
Size: The size operation returns the number of elements in the stack. For example,
if we have a stack containing [10, 20, 30], and we perform the size operation, it
will return 3.
Search: The search operation allows you to search for a specific element in the
stack and returns its position (counting from the top of the stack). If the element is
not found in the stack, it returns -1. For example, if we have a stack containing [10,
20, 30], and we perform the search operation with the value 20, it will return 2
(since 20 is the second element counting from the top of the stack).
The primary operations in the Stack are as follows:
1.Push: Operation to insert a new element in the Stack is termed as Push Operation.
2.Pop: Operation to remove or delete elements from the Stack is termed as Pop Operation.
Working of Stack
A stack is a data structure that stores elements with a Last-In-First-Out (LIFO)
ordering. It works by using a stack pointer to manage the insertion and removal of
elements from the top of the stack.
PUSH operation in Stack
The push operation is an operation in the stack data structure that adds a new
element to the top of the stack. When a new element is pushed onto the stack, it
becomes the new top element, and the size of the stack is increased by 1.

1.Check if the stack is full (if the stack has a fixed size and is already at its
maximum capacity). If the stack is full, the push operation cannot be performed.
2.Increment the top pointer of the stack to move it to the next empty position (i.e.,
the position above the current top element).
3.Add the new element to the position pointed by the top pointer.
4.Update the size of the stack to reflect the addition of the new element.
Algorithm of PUSH Operation in Stack
PUSH(S,TOP,N,X)
Here S is Stack, TOP is Stack Pointer, N is the Maximum Size of the Stack,
X is new element to be inserted
Step 1: If TOP==N
Write "OVERFLOW"
Return
( End of IF Statement)
Step 2: TOP=TOP +1 (Increment the TOP)
Step 3: S[TOP] = X (Insert New Element)
Step 4 END
Program in C to perform PUSH Operation in Stack using Array.
#include <stdio.h>
#define MAX_SIZE 100
int stack[MAX_SIZE];
int top = -1;
void push(int);
int main()
{
push(10);
push(20);
push(30);
push(40);
push(50);
printf("Elements in the Stack\n");
for(int i=top; i>=0;i--)
{
printf("|%d|",stack[i]);
} OUTPUT:-
return 0; 10 pushed to stack
} 20 pushed to stack
void push(int element) 30 pushed to stack
{ 40 pushed to stack
if (top >= MAX_SIZE - 1) 50 pushed to stack
{ Elements in the Stack
printf("Stack Overflow"); |50||40||30||20||10|
}
else
{
top=top+1;
stack[top] = element;
printf("%d pushed to stack\n", element);
}
}
POP operation in a stack:
The POP operation in a stack is typically used in
conjunction with the "PUSH“ operation, which adds
an element to the top of the stack.
Together, these operations allow you to implement a
Last-In-First-Out (LIFO) data structure.
1.Check if the stack is empty. If the stack is
empty, return an error , as popping from an
empty stack is not allowed.
2.Otherwise, retrieve the topmost element from
the stack.
3.Decrement the stack pointer to point to the next
element in the stack.
4.Remove the topmost element from the stack.
5.Return the removed element if necessary.
Algorithm of POP Operation in Stack
POP(S,TOP,N,X)
Here S is Stack,
TOP is Stack Pointer,
N is the Maximum Size of the Stack,
X is element to be deleted
Step 1: If TOP==-1 (Stack Empty)
Write "Underflow"
Return
( End of IF Statement)
Step 2: X= S[TOP] (Delete Top Element)
Step 3: TOP=TOP - 1 (Decrement the Top)
Step 4 END
//Program in C to perform POP operation in Stack {
using Array printf("|%d|",stack[i]);
#include <stdio.h> }
#define MAX_SIZE 100 pop(50);
int stack[MAX_SIZE]; pop(40);
int top = -1; printf("Stack After Pop Operation\n");
void push(int); for(int i=top; i>=0;i--)
void pop(int); {
int main() printf("|%d|",stack[i]);
{ }
push(10); return 0;
push(20); }
push(30); void push(int element)
push(40); {
push(50); if (top >= MAX_SIZE - 1)
printf("Elements Available in the Stack\n"); {
for(int i=top; i>=0;i--) printf("Stack Overflow");
}
else
{
top=top+1; OUTPUT:-
stack[top] = element; 10 pushed to stack
printf("%d pushed to stack\n", element); 20 pushed to stack
}} 30 pushed to stack
void pop(int element) 40 pushed to stack
{ 50 pushed to stack
if (top == - 1) Elements Available in the Stack
{ |50||40||30||20||10|50 element
printf("Stack Underflow"); deleted from Stack
} 40 element deleted from Stack
else Stack After Pop Operation
{ |30||20||10|
element= stack[top];
top=top-1;
printf("%d element deleted from Stack\n",
element);
Applications of stacks :
Parenthesis Matching: In programming languages, parentheses are used to group
expressions and indicate the order of evaluation.
 Parenthesis matching is a common problem where we need to check if a given
expression contains matching opening and closing parentheses. This can be
easily solved using a stack.
 For Example X= a + (b*c), is a valid expression, it has same number of opening
brackets and closing brackets.
 If the expression do not have same number of opening and closing brackets,
that expression will be invalid.

Arithmetic Expression Evaluation: Stacks are often used in programming


languages to evaluate arithmetic expressions. Operators and operands are added to
the stack and the expression is evaluated according to the rules of precedence.
For example, consider the expression 3 * (5 + 2). In this case output will be 21.
Function Call/Return: Stacks are used by programming languages to keep track
of function calls and returns. When a function is called, its return address and local
variables are pushed onto the stack. When the function returns, these values are
popped off the stack. For example, consider a function that calls another function.
The calling function's return address and local variables are pushed onto the stack,
the called function is executed, and then the return address and variables are
popped off the stack.

Undo/Redo Operations: Stacks are commonly used in software applications to


keep track of undo/redo operations. Each time an action is performed, it is added
to the stack.
When undo is requested, the most recent action is popped off the stack and
reversed. When redo is requested, the previously undone action is popped off the
redo stack and re-executed.
Browser History: Stacks are used in web browsers to keep track of visited web
pages. Each time a new page is visited, its URL is added to the stack. When the
back button is clicked, the most recent URL is popped off the stack and the
browser navigates to the previous page.

Compiler Design: Stacks are used in compiler design to check the validity of a
program's syntax. The stack is used to keep track of opening and closing
brackets, braces, and parentheses.
For example, if a program contains an opening brace {, it is pushed onto the
stack. When a closing brace } is encountered, the stack is popped to check if
the opening brace matches the closing brace.
Depth First Search: Stacks are used in graph algorithms such as Depth First Search
(DFS). The DFS algorithm visits all vertices in a graph by exploring as far as
possible along each branch before backtracking. The stack is used to keep track of
vertices that have been visited but not fully explored. Each time a vertex is visited, it
is pushed onto the stack. When all adjacent vertices have been visited, the vertex is
popped off the stack and the algorithm backtracks.

•Expression conversion: Stack can also be used for expression conversion. This is
one of the most important applications of stack.
•The list of the expression conversion is given below:
•Infix to prefix
•Infix to postfix
•Prefix to infix
•Prefix to postfix
•Postfix to infix
1) Arithmetic expressions
Infix Notation:-
The expression which is in the normal format i,e the operator lies in between the operand
Ex: a+b,a*b
Syntax:<Operand><Operator><Operand>

Prefix notation (or) Polish Notation:-


The operator comes first followed by the operands
Ex: +ab,*ab
Syntax:<Operator><Operand><Operand>

Postfix Notation (or) Reverse Polish Notation:-


The operand comes first followed by the operator
Ex:-ab+,ab*
Syntax:<Operand><Operator><Operand>
Conversion of Infix to Postfix Expression
Rules:-
1.Priority of Operators
^ :- Highest Priority
*,/,% :-next Priority
+,- :- Lowest Priority
2. No two operators of same priority can stay together in a stack
column. If Stored POP() has to be done
3. Lowest Priority cannot be Placed before Highest Priority
If the operator is closed within the paranthesis then it has to be POP()
CONVERTION OF INFIX EXPRESSION TO POST FIX (A+B/C*(D+E)-F)
SYMBOL STACK POSTFIX
( (
A ( A FINAL EXPRESSION
+ (+ A ABC/DE+*+F-
B (+ B
/ (+/ AB
C (+/ ABC
* (+* ABC/
( (+*( ABC/
D (+*( ABC/D
+ (+*(+ ABC/D
E (+*(+ ABC/DE
) (+*(+) ABC/DE+
- (- ABC/DE+*+
F (- ABC/DE+*+F
) (-) ABC/DE+*+F-
Convert the INFIX Expression A*B-C/D+E to Prefix
STEP 1:- (A*B)-(C/D)+E
STEP 2:- [*AB]-[/CD]+E
STEP 3:- (T1-T2)+E //*AB=T1,/CD=T2
STEP 4:-[-T1T2]+E //-T1T2=T3
STEP 5:- T3+E
STEP 6:-+T3E
STEP 7:-+-T1T2E
STEP 8:-+-*AB/CDE
Introduction to Tower of Hanoi
•The Tower of Hanoi is a mathematical puzzle also known as Lucas’ Tower .
•It is a game which consists of 3 rods/pegs/stack and n number of disks. These
disks are of different sizes.
•These disks are arranged in an ascending order on a given peg.
•The objective of the game is to move the entire lot of disks of size n to another
peg, following certain simple contraints which are:
• Only a single disk can be moved from one rod to another rod at a given time.
• Only the topmost disk of a peg can be moved to the other.
• No larger disk can be placed on a smaller disk.
• We can use Auxilary tower for temporary storage of disks
STEPS:
1. Move the disk from S to D
2. Move the disk from S to A
3. Move the disk from D to A
4. Move the disk from S to D
5. Move the disk from A to S
6. Move the disk from A to D
7. Move the disk from S to D
Algorithm for Tower of Hanoi
procedure TOH(disk, Source, Dest, Aux):
if disk == 1:
move disk from Source to Dest
else:
TOH(disk - 1, Source, Aux, Dest)
move disk from Source to Dest
TOH(disk - 1, Aux, Dest, Source)
END if
END TOH
#include<stdio.h>
void towers(int,char,char,char);
int main(){
int n;
char src='S',aux='A',dest='D';
printf("enter no of disks\n");
scanf("%d",&n);
towers(n,src,aux,dest); }
void towers(int n, char src,char aux,char dest)
{
if(n==1)
printf("\n move disk from %c to %c",src,dest);
else
{
towers(n-1,src,dest,aux);
towers(1,src,aux,dest);
towers(n-1,aux,src,dest);
}}
QUEUE
Queue
 A queue can be defined as an
ordered list which enables insert
operations to be performed at
one end called REAR and delete
operations to be performed at
another end called FRONT.
 Queue is referred to be as First
In First Out list.
 The principle is simple - the first
item that enters a queue is the
first one to be removed from it.
The primary operations of the Queue:
1.Enqueue: The insertion or Addition of some data elements to the Queue is called
Enqueue. The element insertion is always done with the help of the rear pointer.
2.Dequeue: Deleting or removing data elements from the Queue is termed Dequeue.
The deletion of the element is always done with the help of the front pointer.
Operations :
•Enqueue: The Enqueue operation is used to insert the element at the rear end of the
queue. It returns void.
•Dequeue: It performs the deletion from the front-end of the queue. It also returns the
element which has been removed from the front-end. It returns an integer value.
•Peek: This is the third operation that returns the element, which is pointed by the front
pointer in the queue but does not delete it.
•Queue overflow (isfull): It shows the overflow condition when the queue is completely
full.
•Queue underflow (isempty): It shows the underflow condition when the Queue is
empty, i.e., no elements are in the Queue.
Memory Representation of Queue
Array representation of a queue:
A queue is implemented using a fixed-size array.
The front and rear of the queue are represented by two pointers, front and rear respectively.
When a new element is added to the queue, it is inserted at the rear end, and the rear pointer is
incremented.
Similarly, when an element is removed from the queue, it is removed from the front end, and
the front pointer is incremented.
Linked list representation of a queue:-
 In this representation, a queue is implemented using a linked list.
 Each node in the linked list contains an element and a pointer to the next node.
 The front and rear of the queue are represented by two pointers, front and rear
respectively, which point to the first and last nodes of the linked list.
 When a new element is added to the queue, it is added to the rear end of the linked list,
and the rear pointer is updated to point to the new node.
 Similarly, when an element is removed from the queue, it is removed from the front end of
the linked list, and the front pointer is updated to point to the next node.
Algorithm to Insert a New Element in a
Queue (ENQUEUE Operation)

Here QUEUE is the name of the queue and


MAX is Maximum Size of the queue and
FRONT pointer variable , REAR pointer
variable, ITEM is the element to be inserted.
Step 1: If REAR = MAX-1 then
Write "OVERFLOW"
End of If Statement
Step 2: IF FRONT = -1 (IS QUEUE EMPTY)
Set FRONT = 0
End of If Statement
Step 3: REAR = REAR +1 (Increment
REAR)
Step 4: QUEUE[REAR] = ITEM
Step 5: END
void enqueue(int value)
#include <stdio.h> {
#define MAX_SIZE 10 if (rear == MAX_SIZE - 1)
void enqueue(int); {
int queue[MAX_SIZE]; printf("Queue overflow!");
int front = -1, rear = -1; return;
int main() }
{ if (front == -1)
enqueue(10); {
enqueue(20); front = 0;
enqueue(30); }
printf("Printing QUEUE rear=rear+1;
Elements\n"); queue[rear] = value;
for(int i=front;i<=rear;i++) printf("%d enqueued to queue\n.", value); }
{
printf("|%d|",queue[i]); OUTPUT:-
}
return 0; }
Algorithm to Delete an Element
from a Queue (DEQUEUE Operation)
QUEUE is the name, MAX is
Size ,FRONT , REAR pointer variable,
ITEM element to be inserted. If FRONT
and REAR = -1 then Queue is Empty
Step 1: If FRONT = -1 then
Write "UNDERFLOW"
End of If Statement
Step 2: ITEM = QUEUE[FRONT]
Step 3: IF FRONT = REAR (QUEUE
has only 1 Element)
Set FRONT = -1 and REAR = -1
ELSE
Step 4: FRONT = FRONT+1(Increment
FRONT)
End of If Statement
#include <stdio.h>
#define MAX_SIZE 10 queue[rear] = value;
void enqueue(int); printf("%d enqueued to queue\n", value);}
void dequeue(); void dequeue()
int queue[MAX_SIZE]; {
int front = -1, rear = -1; if (front == -1 )
int main() { {
enqueue(10); printf("Queue underflow!");
enqueue(20); return;
enqueue(30); }
dequeue(); if (front==rear)
dequeue(); {
dequeue(); front = -1;
dequeue(); rear = -1;
return 0;} }
void enqueue(int value) else
{ {
if (rear == MAX_SIZE - 1) { printf("%d dequeued from queue\n", queue[front]);
printf("Queue overflow!"); front++;
return; } }
if (front == -1)
{ front = 0; } }
rear++;
Applications of Queue
Some of the applications of queues include:
1.Operating systems: Operating systems use queues to manage resources such as CPU
time, memory, and input/output devices.
2.Network routing: In computer networks, packets of data are sent from one device to
another. Queues are used to manage the flow of these packets, ensuring that they are
delivered in the correct order and without delay.
3.Customer service: Many businesses use queues to manage customer service requests.
4.Print spooling: When multiple users want to print a document, they are placed in a queue
and processed in the order they were received.
5.Call centers: When customers call a call center, their calls are placed in a queue and
handled by an available agent. This ensures that all customers are served in the order they
called and that no calls are lost or ignored.
6.Task scheduling: In software development, queues are used to schedule tasks such as
database updates, report generation, and file processing.
Simple Queue or Linear Queue
In Linear Queue, an insertion takes place from one end while the deletion
occurs from another end. The end at which the insertion takes place is known
as the rear end, and the end at which the deletion takes place is known as front
end. It strictly follows the FIFO rule.
The major drawback of using a linear Queue is that insertion is done only from
the rear end. If the first three elements are deleted from the Queue, we cannot
insert more elements even though the space is available in a Linear Queue.
Circular Queue
In Circular Queue, all the nodes are represented as circular. It is similar to the linear
Queue except that the last element of the queue is connected to the first element. It is
also known as Ring Buffer, as all the ends are connected to another end.
Operations on Circular Queue
The following are the operations that can be performed on a circular queue:
•Front: It is used to get the front element from the Queue.
•Rear: It is used to get the rear element from the Queue.
•enQueue(value): This function is used to insert the new value in the Queue.
The new element is always inserted from the rear end.
•deQueue(): This function deletes an element from the Queue. The deletion in a
Queue always takes place from the front end.
Algorithm to insert an element in a circular queue

Step 1: IF (REAR+1)%MAX = FRONT


Write " OVERFLOW "
Goto step 4
[End OF IF]
Step 2: IF FRONT = -1 and REAR = -1
SET FRONT = REAR = 0
ELSE IF REAR = MAX - 1 and FRONT ! = 0
SET REAR = 0
ELSE
SET REAR = (REAR + 1) % MAX
[END OF IF]
Step 3: SET QUEUE[REAR] = VAL
Step 4: EXIT
Algorithm to delete an element from the circular queue

Step 1: IF FRONT = -1
Write " UNDERFLOW "
Goto Step 4
[END of IF]
Step 2: SET VAL = QUEUE[FRONT]
Step 3: IF FRONT = REAR
SET FRONT = REAR = -1
ELSE
IF FRONT = MAX -1
SET FRONT = 0
ELSE
SET FRONT = FRONT + 1
[END of IF]
[END OF IF]
Implementation of circular queue using Array

https://onlinegdb.com/_jIUnzofuH
Priority Queue:-
It is a special type of queue in which the elements are arranged based on the priority. It is a
special type of queue data structure in which every element has a priority associated with it.
Suppose some elements occur with the same priority, they will be arranged according to the
FIFO principle. Insertion in priority queue takes place based on the arrival, while deletion in
the priority queue occurs based on the priority. Priority queue is mainly used to implement
the CPU scheduling algorithms.
Insertion in priority queue takes place based on the arrival, while deletion in the priority
queue occurs based on the priority. Priority queue is mainly used to implement the CPU
scheduling algorithms.
There are two types of priority queues
•Ascending priority queue - In ascending priority queue, elements can be inserted in
arbitrary order, but only smallest can be deleted first. Suppose an array with elements 7, 5,
and 3 in the same order, so, insertion can be done with the same sequence, but the order of
deleting the elements is 3, 5, 7.
•Descending priority queue - In descending priority queue, elements can be inserted in
arbitrary order, but only the largest element can be deleted first. Suppose an array with
elements 7, 3, and 5 in the same order, so, insertion can be done with the same sequence,
but the order of deleting the elements is 7, 5, 3.
UNIT-II
UNIT II
Linked Lists: Singly/Linear Linked Lists,
Operations - Insertion and deletion from a list, Linked List
Implementation of Stacks and Queues,
Doubly and Circular Linked Lists, Applications.
Linked Lists:
Singly/Linear Linked
Lists
Linked List:-
The linked list is a linear data structure that contains a sequence of elements such that each
element links to its next element in the sequence. Each element in a linked list is called
"Node".

Single Linked List:-


Single linked list is a sequence of elements in which every element has link to its next
element in the sequence.
In any single linked list, the individual element is called as "Node". Every "Node" contains
two fields, data field, and the next field. The data field is used to store actual value of the node
and next field is used to store the address of next node in the sequence
Operations on Single Linked List
The following operations are performed on a Single
Linked List
•Insertion
•Deletion
•Display
Insertion
In a single linked list, the insertion operation can be performed in three ways.
1.Inserting At Beginning of the list
2.Inserting At End of the list
3.Inserting At Specific location in the list

Inserting At Beginning of the list


•Step 1 - Create a newNode with given value.
•Step 2 - Check whether list is Empty (head == NULL)
•Step 3 - If it is Empty then, set newNode→next = NULL and head = newNode.
•Step 4 - If it is Not Empty then, set newNode→next = head and head = newNode.
Void Insert_at_beginning(int key)
{
struct Node *temp; //temp is a
pointer pointing to the node to be
inserted.
temp = (struct Node*)
malloc(sizeof(struct Node));
The above diagram shows that we have a
if(temp != NULL)
linked list of the following elements:
{
10→20→30.
temp→data = key; //key is the
Once we insert a new node at the beginning,
data value to be inserted
the list will be 50→10→20→30.
temp→next = Head; //this step
will make the incoming node the first
node.
}
}
Inserting At End of the list
•Step 1 - Create a newNode with given value and newNode → next as NULL.
•Step 2 - Check whether list is Empty (head == NULL).
•Step 3 - If it is Empty then, set head = newNode.
•Step 4 - If it is Not Empty then, define a node pointer temp and initialize with head.
•Step 5 - Keep moving the temp to its next node until it reaches to the last node in the list
(until temp → next is equal to NULL).
•Step 6 - Set temp → next = newNode.
void Insert_at_end(int key)
{
struct Node *temp, *Ptr;
temp = (struct Node*) malloc(sizeof(struct Node));
if(temp != NULL)
{
temp->data = key;
temp->Next = NULL;
if(Head == NULL) //This will be true if the list is initially empty
{
Head = temp;
return;
}
Ptr = Head;
while(Ptr->Next != NULL)
Ptr->Next = temp;
}
}
Inserting At Specific location in the list (After a Node)
•Step 1 - Create a newNode with given value.
•Step 2 - Check whether list is Empty (head == NULL)
•Step 3 - If it is Empty then, set newNode → next = NULL and head = newNode.
•Step 4 - If it is Not Empty then, define a node pointer temp and initialize with head.
•Step 5 - Keep moving the temp to its next node until it reaches to the node after which we
want to insert the newNode (until temp1 → data is equal to location, here location is the
node value after which we want to insert the newNode).
•Step 6 - Every time check whether temp is reached to last node or not. If it is reached to
last node then display 'Given node is not found in the list!!! Insertion not possible!!!' and
terminate the function. Otherwise move the temp to next node.
•Step 7 - Finally, Set 'newNode → next = temp → next' and 'temp → next = newNode'
SYNTAX:-
temp->Next = Ptr->Next;
Ptr->Next = temp;
Deletion:- In a single linked list, the deletion operation can be performed in three ways.
1.Deleting from Beginning of the list
2.Deleting from End of the list
3.Deleting a Specific Node

Deleting from Beginning of the list


•Step 1 - Check whether list is Empty (head == NULL)
•Step 2 - If it is Empty then, display 'List is Empty!!! Deletion is not possible' and terminate
the function.
•Step 3 - If it is Not Empty then, define a Node pointer 'temp' and initialize with head.
•Step 4 - Check whether list is having only one node (temp → next == NULL)
•Step 5 - If it is TRUE then set head = NULL and delete temp (Setting Empty list conditions)
•Step 6 - If it is FALSE then set head = temp → next, and delete temp.
void Delete_from_beginning(int key)
{
struct Node *Ptr = Head;
Suppose we initially had the linked list elements if(Head == NULL) //i.e. If the list is
as 10→20→30→40. empty
If we perform deletion of one node at the {
beginning, the linked list will be: return;
20→30→40. }
Head = Head->Next; //linking Head with
the 2nd node of the list
free(Ptr);
}
Deleting from End of the list
•Step 1 - Check whether list is Empty (head == NULL)
•Step 2 - If it is Empty then, display 'List is Empty!!! Deletion is not possible' and
terminate the function.
•Step 3 - If it is Not Empty then, define two Node pointers 'temp1' and 'temp2' and
initialize 'temp1' with head.
•Step 4 - Check whether list has only one Node (temp1 → next == NULL)
•Step 5 - If it is TRUE. Then, set head = NULL and delete temp1. And terminate the
function. (Setting Empty list condition)
•Step 6 - If it is FALSE. Then, set 'temp2 = temp1 ' and move temp1 to its next node.
Repeat the same until it reaches to the last node in the list. (until temp1 →
next == NULL)
•Step 7 - Finally, Set temp2 → next = NULL and delete temp1.
void Delete_at_end(int key)
{
struct Node *Ptr = Head;
struct Node *Prev = NULL;
if(Head == NULL) //If the list is empty
{
return;
}
if(Head->Next == NULL) //If the list has only one
element
{
Head = NULL;
free(Ptr);
}
else
{
while(Ptr->Next != NULL)
{
Prev = Ptr;
Ptr = Ptr->Next;
}
free(Ptr);
}
}
Deleting a Specific Node from the list:- We can use the following steps to delete a specific node
from the single linked list...
•Step 1 - Check whether list is Empty (head == NULL)
•Step 2 - If it is Empty then, display 'List is Empty!!! Deletion is not possible' and terminate the
function.
•Step 3 - If it is Not Empty then, define two Node pointers 'temp1' and 'temp2' and initialize 'temp1'
with head.
•Step 4 - Keep moving the temp1 until it reaches to the exact node to be deleted or to the last node.
And every time set 'temp2 = temp1' before moving the 'temp1' to its next node.
•Step 5 - If it is reached to the last node then display 'Given node not found in the list! Deletion
not possible!!!'. And terminate the function.
•Step 6 - If it is reached to the exact node which we want to delete, then check whether list is having
only one node or not
•Step 7 - If list has only one node and that is the node to be deleted, then set head = NULL and
delete temp1 (free(temp1)).
•Step 8 - If list contains multiple nodes, then check whether temp1 is the first node in the list (temp1
== head).
•Step 9 - If temp1 is the first node then move the head to the next node (head = head → next) and
delete temp1.
•Step 10 - If temp1 is not first node then check whether it is last node in the list (temp1 → next ==
NULL).
SYNTAX:-
Ptr->data = Ptr->Next->data;
Ptr = Ptr->Next;
Ptr->Next = Ptr->Next->Next;
free(Ptr);
Displaying a Single Linked List
•Step 1 - Check whether list is Empty (head == NULL)
•Step 2 - If it is Empty then, display 'List is Empty!!!' and terminate the function.
•Step 3 - If it is Not Empty then, define a Node pointer 'temp' and initialize with head.
•Step 4 - Keep displaying temp → data with an arrow (--->) until temp reaches to the last
node
•Step 5 - Finally display temp → data with arrow pointing to NULL (temp → data --->
NULL).
Linked List Implementation of
Stacks & Queues
Linked List vs Array
ARRAY LINKED LIST
Linked lists are not necessarily contiguous
Arrays are contiguously stored in the memory.
inside the memory.
The array size should be declared inside the We need not declare the size of the list in
program in advance. advance.
It is difficult to change the size of the array We can expand or shrink a linked list any time
afterwards. during the execution of the program.
In a linked list, we cannot randomly access any
Arrays allow random access of elements. element, we need to traverse the list from the
beginning.
Arrays have slower insertion or deletion time Linked lists have a slower search time because
as compared to linked lists. of the absence of random access.
Lists require more memory because we need to
Arrays require less memory per element.
maintain extra pointers.
Linked list implementation of stack
 Instead of using array, we can also use linked
list to implement stack.
 Linked list allocates the memory
dynamically , whereas time complexity in
both the scenario is same for all the
operations i.e. push, pop and peek.
 In linked list implementation of stack, the
nodes are maintained non-contiguously in
the memory.
 Each node contains a pointer to its
immediate successor node in the stack.
 The top most node in the stack always
contains null in its address field.
Adding a node to the stack (Push
operation)
Adding a node to the stack is
referred to as push operation.
Pushing an element to a stack in
linked list implementation is
different from that of an array
implementation.
1.Create a node first and allocate
memory to it.
2.If the list is empty then the item
is to be pushed as the start node of
the list.
3.If there are some nodes in the list
already, then we have to add the
new element in the beginning of
the list.
void push () {
int val;
struct node *ptr =(struct node*)malloc(sizeof(struct node));
if(ptr == NULL) {
printf("not able to push the element");
}
else {
printf("Enter the value");
scanf("%d",&val);
if(head==NULL) {
ptr->val = val;
ptr -> next = NULL;
head=ptr;
}
else {
ptr->val = val;
ptr->next = head;
head=ptr;

}
printf("Item pushed"); } }
Deleting a node from the stack (POP void pop()
operation) {
Deleting a node from the top of stack is int item;
referred to as pop operation. Deleting a node struct node *ptr;
from the linked list implementation of stack is if (head == NULL)
different from that in the array {
implementation. printf("Underflow");
Check for the underflow condition: The }
underflow condition occurs when we try to else
pop from an already empty stack. The stack {
will be empty if the head pointer of the list item = head->val;
points to null. ptr = head;
Adjust the head pointer accordingly: In head = head->next;
stack, the elements are popped only from one free(ptr);
end, therefore, the value stored in the head printf("Item popped");
pointer must be deleted and the node must be
freed. The next node of the head node now }
becomes the head node. }
Display the nodes (Traversing)
Displaying all the nodes of a stack needs void display()
traversing all the nodes of the linked list {
organized in the form of stack. int i;
 Copy the head pointer into a temporary struct node *ptr;
pointer. ptr=head;
 Move the temporary pointer through all if(ptr == NULL)
the nodes of the list and print the value {
field attached to every node. printf("Stack is empty\n");
}
else
{
printf("Printing Stack elements \n");
while(ptr!=NULL)
{
printf("%d\n",ptr->val);
ptr = ptr->next;
} } }
Double Linked List:-
Double linked list is a sequence of elements in which every element has links to its previous
element and next element in the sequence.
In a double linked list, every node has a link to its previous node and next node. So, we can
traverse forward by using the next field and can traverse backward by using the previous field.
Every node in a double linked list contains three fields

Here, 'link1' field is used to store the address of the previous node in the sequence, 'link2' field
is used to store the address of the next node in the sequence and 'data' field is used to store the
actual value of that node.
Operations on Double Linked List
In a double linked list, we perform the following operations...
1.Insertion
2.Deletion
3.Display

Insertion
4.Inserting At Beginning of the list
5.Inserting At End of the list
6.Inserting At Specific location in the list
Inserting At Beginning of the list
•Step 1 - Create a newNode with given value and newNode → previous as NULL.
•Step 2 - Check whether list is Empty (head == NULL)
•Step 3 - If it is Empty then, assign NULL to newNode → next and newNode to head.
•Step 4 - If it is not Empty then, assign head to newNode → next and newNode to head.

Inserting At End of the list


We can use the following steps to insert a new node at end of the double linked list...
•Step 1 - Create a newNode with given value and newNode → next as NULL.
•Step 2 - Check whether list is Empty (head == NULL)
•Step 3 - If it is Empty, then assign NULL to newNode → previous and newNode to head.
•Step 4 - If it is not Empty, then, define a node pointer temp and initialize with head.
•Step 5 - Keep moving the temp to its next node until it reaches to the last node in the list (until temp → next is
equal to NULL).
•Step 6 - Assign newNode to temp → next and temp to newNode → previous.
Inserting At Specific location in the list (After a Node)
•Step 1 - Create a newNode with given value.
•Step 2 - Check whether list is Empty (head == NULL)
•Step 3 - If it is Empty then, assign NULL to both newNode → previous & newNode →
next and set newNode to head.
•Step 4 - If it is not Empty then, define two node pointers temp1 & temp2 and
initialize temp1 with head.
•Step 5 - Keep moving the temp1 to its next node until it reaches to the node after which we
want to insert the newNode (until temp1 → data is equal to location, here location is the node
value after which we want to insert the newNode).
•Step 6 - Every time check whether temp1 is reached to the last node. If it is reached to the last
node then display 'Given node is not found in the list!!! Insertion not possible!!!' and
terminate the function. Otherwise move the temp1 to next node.
•Step 7 - Assign temp1 → next to temp2, newNode to temp1 → next, temp1 to newNode →
previous, temp2 to newNode → next and newNode to temp2 → previous.
Deletion
1.Deleting from Beginning of the list
2.Deleting from End of the list
3.Deleting a Specific Node

Deleting from Beginning of the list


•Step 1 - Check whether list is Empty (head == NULL)
•Step 2 - If it is Empty then, display 'List is Empty!!! Deletion is not possible' and terminate
the function.
•Step 3 - If it is not Empty then, define a Node pointer 'temp' and initialize with head.
•Step 4 - Check whether list is having only one node (temp → previous is equal to temp →
next)
•Step 5 - If it is TRUE, then set head to NULL and delete temp (Setting Empty list
conditions)
•Step 6 - If it is FALSE, then assign temp → next to head, NULL to head → previous and
delete temp.
Deleting from End of the list
•Step 1 - Check whether list is Empty (head == NULL)
•Step 2 - If it is Empty, then display 'List is Empty!!! Deletion is not possible' and terminate
the function.
•Step 3 - If it is not Empty then, define a Node pointer 'temp' and initialize with head.
•Step 4 - Check whether list has only one Node (temp → previous and temp → next both
are NULL)
•Step 5 - If it is TRUE, then assign NULL to head and delete temp. And terminate from the
function. (Setting Empty list condition)
•Step 6 - If it is FALSE, then keep moving temp until it reaches to the last node in the list.
(until temp → next is equal to NULL)
•Step 7 - Assign NULL to temp → previous → next and delete temp.
•Step 1 - Check whether list is Empty (head == NULL)
•Step 2 - If it is Empty then, display 'List is Empty!!! Deletion is not possible' and terminate the
function.
•Step 3 - If it is not Empty, then define a Node pointer 'temp' and initialize with head.
•Step 4 - Keep moving the temp until it reaches to the exact node to be deleted or to the last node.
•Step 5 - If it is reached to the last node, then display 'Given node not found in the list! Deletion
not possible!!!' and terminate the fuction.
•Step 6 - If it is reached to the exact node which we want to delete, then check whether list is having
only one node or not
•Step 7 - If list has only one node and that is the node which is to be deleted then
set head to NULL and delete temp (free(temp)).
•Step 8 - If list contains multiple nodes, then check whether temp is the first node in the list (temp ==
head).
•Step 9 - If temp is the first node, then move the head to the next node (head = head → next),
set head of previous to NULL (head → previous = NULL) and delete temp.
•Step 10 - If temp is not the first node, then check whether it is the last node in the list (temp → next
== NULL).
•Step 11 - If temp is the last node then set temp of previous of next to NULL (temp → previous →
next = NULL) and delete temp (free(temp)).
•Step 12 - If temp is not the first node and not the last node, then
Displaying a Double Linked List
•Step 1 - Check whether list is Empty (head == NULL)
•Step 2 - If it is Empty, then display 'List is Empty!!!' and terminate the function.
•Step 3 - If it is not Empty, then define a Node pointer 'temp' and initialize with head.
•Step 4 - Display 'NULL <--- '.
•Step 5 - Keep displaying temp → data with an arrow (<===>) until temp reaches to the
last node
•Step 6 - Finally, display temp → data with arrow pointing to NULL (temp → data --->
NULL).
Circular Linked List:- A circular linked list is a sequence of elements in which every element
has a link to its next element in the sequence and the last element has a link to the first
element. That means circular linked list is similar to the single linked list except that the last
node points to the first node in the list
Operations
1.Insertion
2.Deletion
3.Display
Before we implement actual operations, first we need to setup empty list. First
perform the following steps before implementing actual operations.
•Step 1 - Include all the header files which are used in the program.
•Step 2 - Declare all the user defined functions.
•Step 3 - Define a Node structure with two members data and next
•Step 4 - Define a Node pointer 'head' and set it to NULL.
•Step 5 - Implement the main method by displaying operations menu and make
suitable function calls in the main method to perform user selected operation.
Insertion
1.Inserting At Beginning of the list
2.Inserting At End of the list
3.Inserting At Specific location in the list

Inserting At Beginning of the list


•Step 1 - Create a newNode with given value.
•Step 2 - Check whether list is Empty (head == NULL)
•Step 3 - If it is Empty then, set head = newNode and newNode→next = head .
•Step 4 - If it is Not Empty then, define a Node pointer 'temp' and initialize with 'head'.
•Step 5 - Keep moving the 'temp' to its next node until it reaches to the last node (until 'temp
→ next == head').
•Step 6 - Set 'newNode → next =head', 'head = newNode' and 'temp → next = head'.
Inserting At End of the list
•Step 1 - Create a newNode with given value.
•Step 2 - Check whether list is Empty (head == NULL).
•Step 3 - If it is Empty then, set head = newNode and newNode →
next = head.
•Step 4 - If it is Not Empty then, define a node pointer temp and initialize
with head.
•Step 5 - Keep moving the temp to its next node until it reaches to the last node
in the list (until temp → next == head).
•Step 6 - Set temp → next = newNode and newNode → next = head.
Inserting At Specific location in the list (After a Node)
•Step 1 - Create a newNode with given value.
•Step 2 - Check whether list is Empty (head == NULL)
•Step 3 - If it is Empty then, set head = newNode and newNode → next = head.
•Step 4 - If it is Not Empty then, define a node pointer temp and initialize with head.
•Step 5 - Keep moving the temp to its next node until it reaches to the node after which we want to insert the
newNode (until temp1 → data is equal to location, here location is the node value after which we want to
insert the newNode).
•Step 6 - Every time check whether temp is reached to the last node or not. If it is reached to last node then
display 'Given node is not found in the list!!! Insertion not possible!!!' and terminate the function. Otherwise
move the temp to next node.
•Step 7 - If temp is reached to the exact node after which we want to insert the newNode then check whether it
is last node (temp → next == head).
•Step 8 - If temp is last node then set temp → next = newNode and newNode → next = head.
•Step 8 - If temp is not last node then set newNode → next = temp → next and temp → next = newNode.
Deletion
1.Deleting from Beginning of the list
2.Deleting from End of the list
3.Deleting a Specific Node

Deleting from Beginning of the list


•Step 1 - Check whether list is Empty (head == NULL)
•Step 2 - If it is Empty then, display 'List is Empty!!! Deletion is not possible' and terminate the function.
•Step 3 - If it is Not Empty then, define two Node pointers 'temp1' and 'temp2' and initialize both 'temp1' and
'temp2' with head.
•Step 4 - Check whether list is having only one node (temp1 → next == head)
•Step 5 - If it is TRUE then set head = NULL and delete temp1 (Setting Empty list conditions)
•Step 6 - If it is FALSE move the temp1 until it reaches to the last node. (until temp1 → next == head )
•Step 7 - Then set head = temp2 → next, temp1 → next = head and delete temp2.
Deleting from End of the list
•Step 1 - Check whether list is Empty (head == NULL)
•Step 2 - If it is Empty then, display 'List is Empty!!! Deletion is not possible' and terminate the
function.
•Step 3 - If it is Not Empty then, define two Node pointers 'temp1' and 'temp2' and initialize 'temp1'
with head.
•Step 4 - Check whether list has only one Node (temp1 → next == head)
•Step 5 - If it is TRUE. Then, set head = NULL and delete temp1. And terminate from the function.
(Setting Empty list condition)
•Step 6 - If it is FALSE. Then, set 'temp2 = temp1 ' and move temp1 to its next node. Repeat the same
until temp1 reaches to the last node in the list. (until temp1 → next == head)
•Step 7 - Set temp2 → next = head and delete temp1.
Deleting a Specific Node from the list
•Step 1 - Check whether list is Empty (head == NULL)
•Step 2 - If it is Empty then, display 'List is Empty!!! Deletion is not possible' and terminate the function.
•Step 3 - If it is Not Empty then, define two Node pointers 'temp1' and 'temp2' and initialize 'temp1' with head.
•Step 4 - Keep moving the temp1 until it reaches to the exact node to be deleted or to the last node. And every time
set 'temp2 = temp1' before moving the 'temp1' to its next node.
•Step 5 - If it is reached to the last node then display 'Given node not found in the list! Deletion not possible!!!'.
And terminate the function.
•Step 6 - If it is reached to the exact node which we want to delete, then check whether list is having only one node
(temp1 → next == head)
•Step 7 - If list has only one node and that is the node to be deleted then set head = NULL and
delete temp1 (free(temp1)).
•Step 8 - If list contains multiple nodes then check whether temp1 is the first node in the list (temp1 == head).
•Step 9 - If temp1 is the first node then set temp2 = head and keep moving temp2 to its next node
until temp2 reaches to the last node. Then set head = head → next, temp2 → next = head and delete temp1.
•Step 10 - If temp1 is not first node then check whether it is last node in the list (temp1 → next == head).
•Step 11- If temp1 is last node then set temp2 → next = head and delete temp1 (free(temp1)).
•Step 12 - If temp1 is not first node and not last node then set temp2 → next = temp1 → next and
Displaying a circular Linked List
•Step 1 - Check whether list is Empty (head == NULL)
•Step 2 - If it is Empty, then display 'List is Empty!!!' and terminate the
function.
•Step 3 - If it is Not Empty then, define a Node pointer 'temp' and initialize
with head.
•Step 4 - Keep displaying temp → data with an arrow (--->) until temp reaches to
the last node
•Step 5 - Finally display temp → data with arrow pointing to head → data.
Applications of Linked list
•With the help of a linked list, the polynomials can be represented as well as we can
perform the operations on the polynomial.
•A linked list can be used to represent the sparse matrix.
•The various operations like student's details, employee's details, or product details can
be implemented using the linked list as the linked list uses the structure data type that can
hold different data types.
•Using linked list, we can implement stack, queue, tree, and other various data structures.
•The graph is a collection of edges and vertices, and the graph can be represented as an
adjacency matrix and adjacency list.
•A linked list can be used to implement dynamic memory allocation.
UNIT -III
UNIT III
Trees: Terminology and Representations,
Types -Binary Trees,
Binary Search Tree,
Heap,
B-Trees,
N-ary Trees,
B+ Trees,
Tree Traversals – Preorder and in-order construction,
Applications of Trees, Hashing.
Trees: Terminology & Representations
Tree:-
 A tree is a very popular non-linear data
structure used in a wide range of
applications.
Tree is a non-linear data structure
which organizes data in hierarchical
structure
In tree data structure, every individual
element is called as Node.
Node in a tree data structure stores the
actual data of that particular element and
link to next element
In a tree data structure, if we
have N number of nodes then we can
have a maximum of N-1 number of
TREE Terminology

Root:- In a tree data structure, the first node is called as Root Node. Every tree
must have a root node. We can say that the root node is the origin of the tree data
structure. In any tree, there must be only one root node. We never have multiple
root nodes in a tree.
Edge:- In a tree data structure, the connecting link between any two
nodes is called as EDGE. In a tree with 'N' number of nodes there will be
a maximum of 'N-1' number of edges.
Parent
In a tree data structure, the node which is a predecessor of any node is called
as PARENT NODE. In simple words, the node which has a branch from it to
any other node is called a parent node. Parent node can also be defined as "The
node which has child / children".
Child
In a tree data structure, the node which is descendant of any node is called
as CHILD Node. In simple words, the node which has a link from its parent
node is called as child node. In a tree, any parent node can have any number of
child nodes. In a tree, all the nodes except root are child nodes.
Siblings:-In a tree data structure, nodes which belong to same Parent are called
as SIBLINGS NODES.
Leaf:- In a tree data structure, the node which does not have a child is
called as LEAF Node. In simple words, a leaf is a node with no child.
In a tree data structure, the leaf nodes are also called as External Nodes.
External node is also a node with no child. In a tree, leaf node is also
called as 'Terminal' node.
Internal Nodes:- In a tree data structure, the node which has atleast one child is
called as INTERNAL Node. In simple words, an internal node is a node with
atleast one child.
In a tree data structure, nodes other than leaf nodes are called as Internal
Nodes. The root node is also said to be Internal Node if the tree has more than
one node. Internal nodes are also called as 'Non-Terminal' nodes.
Degree:- In a tree data structure, the total number of children of a node is
called as DEGREE of that Node. In simple words, the Degree of a node is
total number of children it has. The highest degree of a node among all the
nodes in a tree is called as 'Degree of Tree'
Level:- In a tree data structure, the root node is said to be at Level 0 and the
children of root node are at Level 1 and the children of the nodes which are at
Level 1 will be at Level 2 and so on... In simple words, in a tree each step from
top to bottom is called as a Level and the Level count starts with '0' and
incremented by one at each level (Step).
Height:- In a tree data structure, the total number of edges from leaf node to
a particular node in the longest path is called as HEIGHT of that Node. In a
tree, height of the root node is said to be height of the tree. In a tree, height
of all leaf nodes is '0'.
Depth:- In a tree data structure, the total number of egdes from root node to a
particular node is called as DEPTH of that Node. In a tree, the total number of
edges from root node to a leaf node in the longest path is said to be Depth of the
tree. In simple words, the highest depth of any leaf node in a tree is said to be
depth of that tree. In a tree, depth of the root node is '0'.
Path:- In a tree data structure, the sequence of Nodes and Edges from one
node to another node is called as PATH between that two Nodes. Length
of a Path is total number of nodes in that path.
In below example the path A - B - E - J has length 4.
Sub Tree:- In a tree data structure, each child from a node forms a subtree
recursively. Every child node will form a subtree on its parent node.
Tree Representation
A tree data structure can be represented in two methods.
 List Representation
 Left Child - Right Sibling Representation
List Representation
 In this representation, we use two types of nodes one for representing the
node with data called 'data node' and another for representing only references
called 'reference node’.
 We start with a 'data node' from the root node in the tree. Then it is linked to
an internal node through a 'reference node' which is further linked to any
other node directly. This process repeats for all the nodes in the tree.
Left Child - Right Sibling Representation
 In this representation, we use a list with one type of node which consists of
three fields namely Data field, Left child reference field and Right sibling
reference field.
 Data field stores the actual value of a node, left reference field stores the
address of the left child and right reference field stores the address of the
right sibling node.
 In this representation, every node's data field stores the actual value of that
node.
 If that node has left a child, then left reference field stores the address of
that left child node otherwise stores NULL.
 If that node has the right sibling, then right reference field stores the address
of right sibling node otherwise stores NULL.
Applications of trees:-
•Storing naturally hierarchical data: Trees are used to store the data in the hierarchical
structure.
•Organize data: It is used to organize data for efficient insertion, deletion and searching.
•Trie: It is a special kind of tree that is used to store the dictionary. It is a fast and efficient
way for dynamic spell checking.
•Heap: It is also a tree data structure implemented using arrays. It is used to implement
priority queues.
•B-Tree and B+Tree: B-Tree and B+Tree are the tree data structures used to implement
indexing in databases.
•Routing table: The tree data structure is also used to store the data in routing tables in the
routers.
•Parse Trees: The tree data structure useful in creating parse tree for evaluating arithmetic
expressions.
TREE TRAVERSALS
Tree traversals:-
The term 'tree traversal' means traversing or visiting each node of a tree. There is
a single way to traverse the linear data structure such as linked list, queue, and
stack. Whereas, there are multiple ways to traverse a tree that are listed as follows
-
•Preorder traversal
•Inorder traversal
•Postorder traversal
Algorithm for preorder traversal
Preorder traversal 1.Until all nodes of the tree are not visited
 This technique follows the 'root left right' policy.
2.Step 1 - Visit the root node
 It means that, first root node is visited after that the
3.Step2 - Traverse the left subtree recursively.
left subtree is traversed recursively, and finally,
4.Step 3 - Traverse the right subtree recursively
right subtree is recursively traversed.
 As the root node is traversed before (or pre) the
left and right subtree, it is called preorder traversal.
 So, in a preorder traversal, each node is visited
before both of its subtrees.

The applications of preorder traversal include -


•It is used to create a copy of the tree.
•It can also be used to get the prefix expression of an
expression tree.
 First, we traverse the root node A;
 after that, move to its left subtree B,
 So, for left subtree B, first, the root node B is traversed itself;
 after that, its left subtree D is traversed.
 Since node D does not have any children, move to right subtree E.
 As node E also does not have any children, the traversal of the left subtree of root node A is
completed.
 Now, move towards the right subtree of root node A that is C.
 So, for right subtree C, first the root node C has traversed itself; after that, its left subtree F is
traversed.
 Since node F does not have any children, move to the right subtree G.
 As node G also does not have any children, traversal of the right subtree of root node A is
completed.
 Therefore, all the nodes of the tree are traversed.
 So, the output of the preorder traversal of the above tree is -
A→B→D→E→C→F→G
Postorder traversal
This technique follows the 'left-right root' policy.
It means that the first left subtree of the root node is traversed, after that recursively traverses
the right subtree, and finally, the root node is traversed.
As the root node is traversed after the left and right subtree, it is called postorder traversal.
So, in a postorder traversal, each node is visited after both of its subtrees.

Applications of postorder traversal :-


•It is used to delete the tree.
•It can also be used to get the postfix expression of an expression tree.

Algorithm:- Until all nodes of the tree are not visited


1.Step 1 - Traverse the left subtree recursively.
2.Step 2 - Traverse the right subtree recursively.
3.Step 3 - Visit the root node.
 First, we traverse the left subtree B that will be traversed in postorder.
 After that, we will traverse the right subtree C in postorder. And finally, the root node of the
above tree, i.e., A, is traversed.
 So, for left subtree B, first, its left subtree D is traversed.
 Since node D does not have any children, traverse the right subtree E.
 As node E also does not have any children, move to the root node B.
 After traversing node B, the traversal of the left subtree of root node A is completed.
 Now, move towards the right subtree of root node A that is C.
 So, for right subtree C, first its left subtree F is traversed.
 Since node F does not have any children, traverse the right subtree G.
 As node G also does not have any children, therefore, finally, the root node of the right
subtree, i.e., C, is traversed.
 The traversal of the right subtree of root node A is completed.
 At last, traverse the root node of a given tree, i.e., A.
 After traversing the root node, the postorder traversal of the given tree is completed.
 Therefore, all the nodes of the tree are traversed.
 So, the output of the postorder traversal of the above tree is -
D→E→B→F→G→C→A
Inorder traversal:- This technique follows the 'left root right' policy. It means
that first left subtree is visited after that root node is traversed, and finally, the
right subtree is traversed.
As the root node is traversed between the left and right subtree, it is named
inorder traversal. So, in the inorder traversal, each node is visited in between of
its subtrees.
Applications of Inorder traversal -
•It is used to get the BST nodes in increasing order.
•It can also be used to get the prefix expression of an expression tree.

Algorithm:- Until all nodes of the tree are not visited


1.Step 1 - Traverse the left subtree recursively.
2.Step 2 - Visit the root node.
3.Step 3 - Traverse the right subtree recursively.
First, we traverse the left subtree B that will be traversed in inorder.
After that, we will traverse the root node A. And finally, the right subtree C is
traversed in inorder. So, for left subtree B, first, its left subtree D is traversed.
Since node D does not have any children, so after traversing it, node B will be
traversed, and at last, right subtree of node B, that is E, is traversed.
Node E also does not have any children; therefore, the traversal of the left subtree
of root node A is completed. After that, traverse the root node of a given tree,
i.e., A. At last, move towards the right subtree of root node A that is C.
So, for right subtree C; first, its left subtree F is traversed.
Since node F does not have any children, node C will be traversed, and at last, a
right subtree of node C, that is, G, is traversed.
Node G also does not have any children; therefore, the traversal of the right
subtree of root node A is completed.
As all the nodes of the tree are traversed, the inorder traversal of the given tree is
completed.
The output of the inorder traversal of the above tree is -
PREORDER TRAVERSAL,INORDER TRAVERSAL,POST ORDER
TRAVERSAL
TYPES OF TREES
Binary Tree
The Binary tree means that the node can have maximum two children.
These two children are usually called:
•Left child
•Right child
Properties of Binary Tree
 At each level of i, the maximum number of nodes is 2i.
 The height of the tree is defined as the longest path from the root node to the leaf
node. In general, the maximum number of nodes possible at height h is (2 0 + 21 + 22+
….2h) = 2h+1 -1.
 The minimum number of nodes possible at height h is equal to h+1.
 The minimum height can be computed as:h = log2(n+1) – 1
 The maximum height can be computed as:h= n-1

Types of Binary Tree


 Full/ proper/ strict Binary tree
 Complete Binary tree
 Perfect Binary tree
 Degenerate Binary tree
 Balanced Binary tree
Full/ proper/ strict Binary tree
The full binary tree is also known as a strict binary tree. The tree can only be considered as the
full binary tree if each node must contain either 0 or 2 children.

Properties of Full Binary Tree


•The number of leaf nodes is equal to the number of internal nodes plus 1.
•The maximum number of nodes is the same as the number of nodes in the binary tree,
i.e., 2h+1 -1.
•The minimum number of nodes in the full binary tree is 2*h-1.
•The minimum height of the full binary tree is log2(n+1) - 1.
•The maximum height of the full binary tree can be computed as: h = n+1/2
Complete Binary Tree
The complete binary tree is a tree in which all the nodes are completely filled except the last
level. In the last level, all the nodes must be as left as possible. In a complete binary tree, the
nodes should be added from the left.

Properties of Complete Binary Tree


•The maximum number of nodes in complete binary tree is 2h+1 - 1.
•The minimum number of nodes in complete binary tree is 2h.
•The minimum height of a complete binary tree is log2(n+1) - 1.
•The maximum height of a complete binary tree is
Perfect Binary Tree Degenerate Binary Tree
A tree is a perfect binary tree if all the The degenerate binary tree is a tree in which all
internal nodes have 2 children, and all the internal nodes have only one children.
the leaf nodes are at the same level.
It is also known as a right-
skewed tree as all the
nodes have a right child
only.

It is also known as a
left-skewed tree as all
the nodes have a left
child only.
Balanced Binary Tree
The balanced binary tree is a tree in which both the left and right trees differ by atmost 1.
Binary Tree Representations
A binary tree data structure is represented using
two methods.
1. Array Representation
2. Linked List Representation
Array Representation of Binary Tree
In array representation of a binary tree, we use one-dimensional array (1-D Array) to
represent a binary tree.
To represent a binary tree of depth 'n' using array representation, we need one
dimensional array with a maximum size of 2n + 1.
Linked List Representation of Binary
Tree
We use a double linked list to represent a
binary tree. In a double linked list, every
node consists of three fields. First field
for storing left child address, second for
storing actual data and third for storing
right child address.
Binary Tree Operations
Binary trees support several fundamental
operations, including insertion, deletion, After inserting a node 6,
searching, and traversals
1. Insertion
Insertion involves adding a new node to the
binary tree. In a binary tree, a new node is usually
inserted at the first available position in level
order to maintain the completeness of the tree.
Deletion
Deletion involves removing a node from the binary tree. In a binary tree, the
node to be deleted is replaced by the deepest and rightmost node to maintain the
tree's structure.
Search
Searching involves finding a node with a given value in the binary tree. The search
operation can be implemented using any traversal method (in-order, pre-order, post-
order, or level-order).

search for the value 5 in the following binary tree:


Using level-order traversal:
•Visit node 1
•Visit node 2
•Visit node 3
•Visit node 4
•Visit node 5 (found)
Traversal
Traversal involves visiting all the nodes in the binary tree in a specific order.
The main traversal methods are in-order, pre-order, post-order, and level-order.
•In-order Traversal (Left, Root, Right): 4, 2, 5, 1, 3
•Pre-order Traversal (Root, Left, Right): 1, 2, 4, 5, 3
•Post-order Traversal (Left, Right, Root): 4, 5, 2, 3, 1
•Level-order Traversal (Breadth-First): 1, 2, 3, 4, 5
BINARY TREE TRAVERSALS:
The process of visiting the nodes is known as tree traversal. There are three types
traversals used to visit a node:
•Inorder traversal Preorder Traversal (Root, Left, Right)
•Preorder traversal void preorder(struct Node* root) {
•Postorder traversal if (root == NULL) return;
printf("%d ", root->data);
Inorder Traversal (Left, Root, Right) preorder(root->left);
preorder(root->right);}
void inorder(struct Node* root) { Postorder Traversal (Left, Right, Root)
if (root == NULL) return; void postorder(struct Node* root) {
inorder(root->left); if (root == NULL) return;
printf("%d ", root->data);
inorder(root->right); postorder(root->left);
} postorder(root->right);
printf("%d ", root->data);
}
Binary Search tree:-
In a Binary search tree, the value of left node must be smaller than the parent node, and
the value of right node must be greater than the parent node. This rule is applied
recursively to the left and right subtrees of the root.

Advantages of Binary search tree


•Searching an element in the Binary search tree is easy as we always have a hint that which
subtree has the desired element.
•As compared to array and linked lists, insertion and deletion operations are faster in BST.
Creation of Binary Search tree with the data elements 45, 15, 79, 90, 10, 55, 12, 20, 50
First, we have to insert 45 into the tree as the root of the tree.
Step 1 - Insert 45 Step 3 - Insert 79.
As 79 is greater than 45, so insert it as
the root node of the right subtree.

Step 2 - Insert 15.


As 15 is smaller than 45, so insert it as the root
node of the left subtree.
Step 4 - Insert 90. Step 5 - Insert 10.
90 is greater than 45 and 79, so it will 10 is smaller than 45 and 15, so it will be
be inserted as the right subtree of 79. inserted as a left subtree of 15.
Step 6 - Insert 55. Step 7 - Insert 12.
55 is larger than 45 and smaller than 12 is smaller than 45 and 15 but greater
79, so it will be inserted as the left than 10, so it will be inserted as the right
subtree of 79. subtree of 10.
Step 8 - Insert 20. Step 9 - Insert 50.
20 is smaller than 45 but greater 50 is greater than 45 but smaller than
than 15, so it will be inserted as 79 and 55. So, it will be inserted as a
the right subtree of 15. left subtree of 55.
Searching in Binary search tree
1.First, compare the element to be searched with the root element of the tree.
2.If root is matched with the target element, then return the node's location.
3.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.
4.If it is larger than the root element, then move to the right subtree.
5.Repeat the above procedure recursively until the match is found.
6.If the element is not found or not present in the tree, then return NULL.
Suppose we have to find node 20 from the below tree.

1
2

3
Algorithm to search an element in Binary search tree
Search (root, item)
Step 1 - if (item = root → data) or (root = NULL)
return root
else if (item < root → data)
return Search(root → left, item)
else
return Search(root → right, item)
END if
Step 2 - END
Deletion in Binary Search tree
•The node to be deleted is the leaf node, or,
•The node to be deleted has only one child, and,
•The node to be deleted has two children

When the node to be deleted is the leaf node


It is the simplest case to delete a node in BST. Here, we have to replace the leaf node with
NULL and simply free the allocated space.
When the node to be deleted has only one child
In this case, we have to replace the target node with its child, and then delete the child
node. It means that after replacing the target node with its child node, the child node will
now contain the value to be deleted. So, we simply have to replace the child node with
NULL and free up the allocated space.
When the node to be deleted has two children
•First, find the inorder successor of the node to be deleted.
•After that, replace that node with the inorder successor until the target node is placed at
the leaf of tree.
•And at last, replace the node with NULL and free up the allocated space.
Insertion in Binary Search tree
To insert an element in BST, we have to start searching from the root node; if the node to be
inserted is less than the root node, then search for an empty location in the left subtree. Else,
search for the empty location in the right subtree and insert the data. Insert in BST is similar
to searching, as we always have to maintain the rule that the left subtree is smaller than the
root, and right subtree is larger than the root.
Heap
A heap is a complete binary tree, and the binary tree is a tree in which the node can
have utmost two children.
There are two types of the heap:
•Min Heap
•Max heap
Min Heap: The value of the parent node should be less than or equal to both children.
Max Heap: The value of the parent node is greater than or equal to its children.
Insertion in the Max Heap tree 44, 33, 77, 11, 55, 88, 66
To create the max heap tree, we need to consider the following two cases:
•First, we have to insert the element in such a way that the property of the complete binary
tree must be maintained.
•Secondly, the value of the parent node should be greater than the either of its child.

Step 1: First we add the 44 element in the tree

Step 2: The next element is 33. As we know that insertion in the binary tree always
starts from the left side so 44 will be added at the left of 33
Step 3: The next element is 77 and it will be added to the right of the 44
As we can observe in the above tree that it does not satisfy the max heap property, i.e.,
parent node 44 is less than the child 77. So, we will swap these two values

Step 4: The next element is 11. The node 11 is added to the left of 33
Step 5: The next element is 55. To make it a complete binary tree, we will add the
node 55 to the right of 33

As we can observe in the above figure that it does not satisfy the property of the max
heap because 33<55, so we will swap these two values
Step 6: The next element is 88. The left subtree is completed so we will add 88 to the left
of 44
As we can observe in the above figure that it does not satisfy the property of the max
heap because 44<88, so we will swap these two values

Step 7: As we can observe in the above figure that 88 >77,so swap these values
Step 8:- The next element is 66. To make a complete binary tree, we will add the 66
element to the right side of 77
B TREE
B-Tree(Height balanced M way search Tree)

A B-Tree is a self-balancing search tree in which multiple nodes can


have more than two children.

Properties of a B-Tree (of order m)


All leaf nodes must be at same level.
All nodes except root must have at least [m/2]-1keys and maximum of
m-1 keys
All non leaf nodes except root must have at least m/2 children
If the rot node is a non leaf node,then it must have atleast 2 children
A non leaf node with n-1 keys must have n number of children
All the key values in a node must be in ascending order.
OPERATIONS IN B TREE
INSERTION
 In a B-tree ,a new element must be added only at the leaf node.
 Check whether the tree is empty
 If tree is empty, then find the suitable leaf node to which the new key value
is added using binary search tree logic.
 If that leaf node has empty position add the new key value to that leaf node
ascending order of the key value within the node
 If that leaf node is already full, split that leaf node by sending middle value
to its parent node. Repeat the same until the sending value is fixed into a
node
 If the splitting is performed at root node then the middle value becomes new
root node for the tree and the height of the tree is increased by one
The data is inserted into the tree using the binary search insertion and once the keys reach the
maximum number, the node is split into half and the median key becomes the internal node while
the left and right keys become its children.

All the leaf nodes must be on the same level.


The keys, 5, 3, 21, 9, 13 are all added into
the node according to the binary search
property but if we add the key 22, it will
violate the maximum key property. Hence,
the node is split in half, the median key is
shifted to the parent node and the insertion
is then continued.
Deletion operation
The deletion operation in a B tree is slightly different from the deletion operation of a
Binary Search Tree.
Case 1 − If the key to be deleted is in a leaf node and the deletion does not violate the
minimum key property, just delete the node.
Case 2 − If the key to be deleted is in a leaf node but the deletion violates the minimum key
property, borrow a key from either its left sibling or right sibling. In case if both siblings
have exact minimum number of keys, merge the node in either of them.
Case 3 − If the key to be deleted is in an internal node, it is replaced by a key in either left
child or right child based on which child has more keys. But if both child nodes have
minimum number of keys, theyre merged together.
Case 4 − If the key to be deleted is in an internal node violating the minimum keys property,
and both its children and sibling have minimum number of keys, merge the children. Then
merge its sibling with its parent.
B+ Tree:-
A B+ Tree is a balanced tree data structure that maintains sorted data and allows
searches, sequential access, insertions, and deletions . It is a type of self-balancing tree
and a variant of the B-Tree.
The properties of B+ trees are similar to the properties of B trees, except that the B trees can
store keys and records in all internal nodes and leaf nodes while B+ trees store records in
leaf nodes and keys in internal nodes.

You might also like