Data Structures Using C - Jagtap, Mali, 2022
Data Structures Using C - Jagtap, Mali, 2022
Data Structures Using C - Jagtap, Mali, 2022
Amol M Jagtap
Rajarambapu Institute of Technology, India
Ajit S Mali
Rajarambapu Institute of Technology, India
First edition published 2022
by CRC Press
6000 Broken Sound Parkway NW, Suite 300, Boca Raton, FL 33487-2742
© 2022 selection and editorial matter, Lavanya Sharma; individual chapters, the contributors
Reasonable efforts have been made to publish reliable data and information, but the author and
publisher cannot assume responsibility for the validity of all materials or the consequences of
their use. The authors and publishers have attempted to trace the copyright holders of all material
reproduced in this publication and apologize to copyright holders if permission to publish in this
form has not been obtained. If any copyright material has not been acknowledged please write and
let us know so we may rectify in any future reprint.
Except as permitted under U.S. Copyright Law, no part of this book may be reprinted, reproduced,
transmitted, or utilized in any form by any electronic, mechanical, or other means, now known
or hereafter invented, including photocopying, microfilming, and recording, or in any information
storage or retrieval system, without written permission from the publishers.
For permission to photocopy or use material electronically from this work, access www.copyright.
com or contact the Copyright Clearance Center, Inc. (CCC), 222 Rosewood Drive, Danvers, MA
01923, 978-750-8400. For works that are not available on CCC please contact m
pkbookspermissions@
tandf.co.uk
Trademark notice: Product or corporate names may be trademarks or registered trademarks and are
used only for identification and explanation without intent to infringe.
DOI: 10.1201/9781003105800
Typeset in Palatino
by codeMantra
Contents
Preface.................................................................................................................. xvii
Authors ................................................................................................................. xix
v
vi Contents
4.6.1.1
Creation of Doubly Linear Linked List ............. 117
4.6.1.2
Delete an Element from Doubly Linear
Linked List ............................................................ 119
4.6.2 Program: Implementation of Doubly Linear
Linked List............................................................................ 120
4.6.3 Insert New Node at the Start of Doubly Linear
Linked List............................................................................ 124
4.6.4 Insert New Node at Last Position of Doubly
Linked List............................................................................ 125
4.6.5 Insert New Node at the Specifed Position in
Doubly Linear Linked List ................................................. 125
4.7 Doubly Circular Linked List ........................................................... 127
4.7.1 Program: Implementation of Doubly Circular
Linked List............................................................................ 127
4.8 Stack Implementation Using Linked List ...................................... 131
4.8.1 Representation of Stack Using Linked List ..................... 131
4.8.2 Program: Stack Implementation Using Linked List ...... 132
4.9 Linear Queue Implementation Using Linked List ....................... 135
4.9.1 Representation of Queue Using Linked List.................... 135
4.9.2 Program: Linear Queue Implementation Using
Linked List ........................................................................... 136
4.10 Circular Queue Implementation Using Linked List.................... 139
4.10.1 Operations on Circular Queue .......................................... 139
4.10.2 Program: Circular Queue Implementation Using
Linked List ........................................................................... 141
4.11 Interview Questions ......................................................................... 144
4.12 Multiple Choice Questions .............................................................. 145
1. There are costs and benefts associated with each data structure and
algorithm. Practitioners need an in-depth understanding of how to
evaluate the costs and benefts to be able to adapt to emerging design
challenges.
2. It is rather common to reduce time requirements at the expense of
increased space requirements or vice versa. Programmers regularly
face trade-offs at all stages of software design and implementation,
so the concept needs to be frmly anchored.
3. Programmers should be suffciently knowledgeable about current
practices to avoid reinventing the wheel. Hence, programmers need
to learn the commonly used data structures, their associated algo-
rithms, and the most frequently encountered design models found
in programming.
xvii
xviii Preface
Amol M. Jagtap
Ajit S. Mali
Authors
xix
1
Fundamental Principles of
Algorithm and Recursion
DOI: 10.1201/9781003105800-1 1
2 Data Structures using C
1. FOR… ENDFOR
2. WHILE… ENDWHILE
1. IF… ENDIF
2. WHILE… ENDWHILE (this is both a loop and a conditional clause
by the way)
3. CASE… ENDCASE
if (I < 10)
{
I++;
}
Step 5: Stop.
1.1.3 Flowchart
The graphical representation of any program is referred to as fowcharts. A
fowchart is a kind of diagram that represents an algorithmic program, a
workfow or operations. A fowchart aims to provide people with a common
language to understand a project or process. Developers often use it as a
program-planning tool for troubleshooting a problem. Each fowchart pro-
vides the solution to a specifc problem. There are a few standard graphics
symbols, which are used in the fowchart as follows:
Or
On-Page Connector Off-Page Connector
5. Question or Decision
The diamond symbol is used as a representation of the true or false
statement tested in a decision symbol.
6. Connector
A fowchart is divided into two or more smaller fowcharts, con-
sistent with project requirements. This connector is most often used
when a fowchart does not ft on a single page or has to be split
into sections. A connector symbol, which is a small circle called an
On-Page Connector, with a number inside it, allows you to connect
two fowcharts on the same page.
A connector symbol that looks like a pocket on a shirt, called off-
page connector allows you to connect to a fow diagram on another
page.
Advantages of fowchart:
1. Flowcharts are one of the best ways of documenting programs.
2. Flowcharts are easier to understand compared to algorithms and
pseudo-codes.
3. It helps us to debug and analyze processes.
4. It helps us understand how to think or make decisions to formu-
late the problem.
Disadvantages of fowchart:
Start
Input any number
Take input as
base and height rem = number mod 2
Yes No
If(rem=0)
area=(base*height)/2
Stop
Stop
that which values we can store in that particular data types and operations
that can be performed on them without any idea of how these data types are
implemented. Therefore, a programmer just needs to know what a kind of
data can do, but not how it’s going to do it. ADT may be considered a black
box that hides the internal structure and design of the data type. We are now
going to defne three ADTs: List ADT, Stack ADT, Queue ADT.
Push () – Insert an item on one end of the stack called the top.
Pop () – Removes and returns the item to the top of the stack, if it is not
empty.
Top () – Returns the element to the top of the stack without deleting it,
if the stack is not empty.
Size () – Returns the number of items within the stack.
IsEmpty () – Returns true if it is empty, otherwise returns false.
IsFull () – Returns true if the stack is full or returns false.
done at the rear and the deletion is done at the front. The following opera-
tions may be carried out in the queue:
Enqueue () – Insert an element at the end of the queue that is the rear
end.
Dequeue () – Delete the frst item from the front end of the queue, if the
queue is not empty.
Size () – Returns the number of items within the queue.
IsEmpty () - Returns true if the queue is empty, otherwise return false.
IsFull () – Returns true if the queue is full or returns false.
From these descriptions of ADTs, we can see that the descriptions do not
specify how these ADTs will be represented and how the operations will be
carried out. There can be alternative ways to implement ADTs using an array
or linked list, for example, the list ADT can be implemented using arrays as
statically, or singly linked list or doubly linked list as dynamically. Likewise,
stack ADT and Queue ADT or other ADTs can be implemented using related
arrays or linked lists.
Data structure
2. Data space:
i. Heavily dependent on computer’s architecture and compiler.
ii. Magnitude of data that program works.
In programming languages, there are different kinds of
data and different number of bytes to store particular data are
required. Such that the character data type requires 1 byte of
memory, integer requires 4 bytes, foat requires 4 bytes, double
requires 8 bytes, etc. This varies from one compiler to another.
Choosing a “smaller” data type will affect the overall use of
space in the program. Choose the appropriate type when work-
ing with arrays.
3. Stack space:
Each time a function is called, the following data are recorded in
the stack.
i. The return address.
ii. Value of all local variables and value of formal parameters.
iii. Bindings of all references and constant reference parameters.
Examples:
1. Non-recursive algorithm sum(a, n)
{
S = 0.0;
for i =1 to n do
S = S + a[i] ;
return S;
}
{
if (n<=0) then return 0.0;
else return Rsum (a, n-1) + a[n];
}
However, the time taken to execute one instruction, this quantity varies from
system to system or computer to computer. Therefore, we only consider the
number of instructions in an algorithm to be a time complexity.
For most algorithms, running time depends on the size of the input. Run
time is expressed in T (n) for a function T on input size n. Suppose there is
if….. else statement that may execute or not, then in that situation variable
running time.
In general, algorithm time complexity is calculated in the following ways:
1. Prior estimate:
Prior estimates concern theoretical or mathematical calculations.
Theoretical or mathematical calculations use the asymptotic nota-
tion for representation.
2. Posterior estimate or testing:
The designed algorithm is implemented on a machine. It deals
with the writing of a program and thus depends on the operating
system, compiler, etc.
Performance analysis: The primary goal is to determine the time and space
required to run the program to its completion in terms of system time and
system memory.
Prior analysis: Deals with computations of count of statement in a given
algorithm. The count indicates how often each instruction is executed.
1. Example 1
3. S=0;
4. for (i=1 to n) do
5. S = S + a[i];
6. return s;
7. }
2. Example 2:
1. Algorithm add(a,b,c,m,n)
2. {
3. for (i=1 to m) do
4. for (j=1 to n) do
5. C[i, j]=a[i, j]+b[i, j]
6. }
#include<stdio.h>
int main() // main function is called as direct
recursive function.
{
printf("Hello\n");
main(); // call to the main function
return 0;
}
Output:
Print Hello infnite times.
In the above program, the main () function is invoked by itself is
called as direct recursive function.
2. Indirect recursive algorithm: Algorithm A is considered an indirect
recursive algorithm if it calls another algorithm B that in turn calls
A.
Example:
#include<stdio.h>
void demo();
int main() //main function is called as indirect
recursive function.
{
printf("Hello\n");
demo();
return 0;
}
void demo()
{
main(); // call to the main function inside demo
function and demo function is called by // main
function
}
Output:
14 Data Structures using C
Output:
Enter a number to calculate its factorial
4
4! = 24
else
{
f = factorial(n);
printf("%d! = %ld\n", n, f);
}
return 0;
}
long factorial(int n)
{
if (n == 0)
return 1;
else
return(n * factorial(n-1));
}
Output:
Enter an integer to fnd its factorial
4
4! = 24
Output:
The sum of digits in 123 is 6.
{
if (n == 0)
return 0;
return (n % 10 + sum_of_digit(n / 10));
}
int main()
{
int num = 123;
int result = sum_of_digit(num);
printf("Sum of digits in %d is %d\n", num, result);
return 0;
}
Output:
Sum of digits in 123 is 6
Output:
Enter a positive integer: 5
Sum = 15
int main()
{
int num;
printf("Enter a positive integer: ");
scanf("%d", &num);
printf("Sum = %d",addNumbers(num));
return 0;
}
int addNumbers (int n)
{
if(n != 0)
return n + addNumbers(n-1);
else
return n;
}
Output:
Enter a positive integer: 5
Sum = 15
Output:
Enter a positive number: 7
7 is a prime number
return 0;
}
Output:
Enter a positive number: 21
21 is not a prime number
reverse_number=reverse_function(num);
printf("\nAfter reverse, the number is
:%d",reverse_number);
return 0;
}
int rev=0, rem;
int reverse_function(int num)
{
while(num!=0)
{
rem=num % 10; // separate first digit of a number
rev=(rev * 10 )+ rem; //multiply each intermediate
number (rev) by 10 and add separated //digit into it gives you
reverse number
num = num / 10; // delete first digit of a number
}
return rev;
}
Output:
Enter any number: 546
After reverse, the number is: 645
Output:
Enter any number: 123
After reverse, the number is: 321
#include<stdio.h>
void recursion(int n)
{
if(n == 0)
return;
printf("%d",n);
recursion(n-2);
}
int main()
{
recursion(6);
return 0;
}
A. 642
B. 654321
C. 662
D. 6420
Answer: (A)
Explanation:
Recursion function’s frst call print value 6, second call print value
4, third call print value 2 and the fourth call will execute return state-
ment when the value becomes 0, so the output of the program is 642.
22 Data Structures using C
#include<stdio.h>
int main()
{
printf("Hello students");
main();
return 0;
}
Explanation:
A sequential solution of any program that wrote in any natural
language is called as an algorithm.
A. Statement 1 is false
B. Statement 2 is false
C. Statements 1 and 2 both are false
D. Statements 1 and 2 both are true
Answer: (D)
DOI: 10.1201/9781003105800-2 27
28 Data Structures using C
FIGURE 2.1
Stack.
Example: In the stack, pop the element which is last to be placed on the
stack and push the element at the top of the stack, such an order is called last
in frst out (LIFO).
Concept of stack:
A stack is an ordered list in which all insertions and deletions are performed
at one end, referred to as top (Figure 2.1).
#define size 10
struct stack
{
FIGURE 2.2
Stack implementation using one-dimensional array data type.
Sequential Representation of Linear Data 29
FIGURE 2.3
Stack implementation using structure data type.
int s[size];
int top;
} st ;
We will write push and pop function to implement the stack, and before
pushing, we will check whether or not stack is full. Before popping an
element from stack, we will check whether or not the stack is empty.
Empty stack operation (Figure 2.4):
Top initially set as −1.
FIGURE 2.4
Stack empty condition.
30 Data Structures using C
FIGURE 2.5
Stack full condition.
int stack_full()
{
if(st.top == (size-1))
return 1;
else
return 0;
}
Step 1: Start
Step 2: Initialize
Set top= -1
Step 3: Repeat steps 3 to 5 until top < max size-1
Step 4: Read item.
Step 5: Set top = top +1
Step 6: Set stack [top] = item
Step 7: Otherwise Print “stack is overfow”
Step 8: Stop
An algorithm for the Pop operation: the pop ( ) removes the element from
the top of the stack (Figure 2.6).
Step 1: Start
Step 2: Repeat step 3 to 5 until top >= 0
Step 3: Set item = Stack[top]
Step 4: Set top = top -1
Step 5:Print, No deleted is, Item.
Step 6: Otherwise Print stack under fows.
Step 7: Stop
int pop()
{
FIGURE 2.6
Performing push and pop operation on a stack.
32 Data Structures using C
int item;
item=st.s[st.top];
st.top--;
return(item);
}
Output:
Algorithm
1. Check the character is operand or operator.
2. If it is an operand, then push it on the operand stack.
3. If it is an operator, then place it in the operator stack; then check
whether it is a unary or binary operator.
4. If it is a unary operator, then pop current one operand from the oper-
and stack and do the operation on that operand and result which is
operand itself is stored on the operand stack.
5. If it is a binary operator, then pop current two operands from the
operand stack and do the operation on that operands and result
which is operand itself is stored on the operand stack.
6. Do the same procedure till the character sting get over.
Solution:
The frst given formula is in the prefx form, therefore scan the string or
formula from right to left.
Algorithm
1. Check the character is operand or operator.
2. If it is an operand, then push it on the operand stack.
3. If it is an operator, then place it in the operator stack; then check
whether it is a unary or binary operator.
4. If it is a unary operator, then pop current one operand from the
operand stack and do the operation on that operand and result,
which is operand itself is stored on the operand stack.
5. If it is a binary operator, then pop current two operands from the
operand stack and do the operation on that operands and result,
which is operand itself is stored on the operand stack.
6. Do the same procedure till the character sting get over.
2.3.3 Backtracking
Backtracking is used in algorithms where there are steps along a certain path
from a point of departure to a certain target.
In all of these cases, there are alternatives to be made among several options.
We need some way to remember these decision points in case we want to
come back and try the alternative.
Sequential Representation of Linear Data 37
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define MAX 20
char str[MAX],stack[MAX];
int top=-1;
void push(char c)
{
stack[++top]=c;
}
char pop()
{
return stack[top--];
}
void post_in()
{
int n,i,j=0;
char a,b,op,x[20];
printf("Enter the postfix expression\n");
fflush(stdin);
gets(str);
strrev(str);
n=strlen(str);
for(i=0;i<MAX;i++)
stack[i]='\0';
printf("Infix expression is: \t");
for(i=0;i<n;i++)
{
if(str[i]=='+'|| str[i]=='-'|| str[i]=='/'|| str[i]=='*')
{
push(str[i]);
}
else
{
Sequential Representation of Linear Data 39
x[j]=str[i];
j++;
x[j]=pop();
j++;
}
}
x[j]=str[top--];
strrev(x);
printf("%s\n",x);
}
int main()
{
int ch;
while(1)
{
printf("Enter choice 1 postfix to infix 2.exit\n");
scanf("%d",&ch);
switch(ch)
{
case 1:
post_in();
break;
case 2:
exit(0);
default: printf("Wrong chioce\n");
}
printf("Enter 1 to continue, 0 to exit\n");
scanf("%d",&ch);
if(ch==0)
{
break;
}
}
return 0;
}
Output:
40 Data Structures using C
In the above algorithm, from_rod refers to the source rod, to_rod refers to the
destination rod and aux_rod refers to the auxiliary rod.
int main()
{
int n = 3; // Number of disks
towerOfHanoi(n, 'A', 'C', 'B'); // A, B and C are names
of rods
return 0;
}
Output:
Sequential Representation of Linear Data 41
Note that if the discs are three, then total moves are (2 3 − 1), i.e., 7.
That is, if there are n discs, total (2 n − 1) moves are required to solve
this puzzle.
2.5 Queue
Queue is non-primitive linear data structure. Queue is a data structure that
allows us to use two ends of it named as front and rear. In the queue data
structure, from the front, one can remove elements, and from the rear, one
can insert elements. Queue is also called as frst in frst out (FIFO). A queue
is a useful data structure for programming. It is similar to the ticket queue
outside a cinema, where the frst person in the queue is the frst person who
gets the ticket.
Types of Queues
There are four types of queues, as follows:
FIGURE 2.7
Linear queue representation using an array.
Sequential Representation of Linear Data 43
FIGURE 2.8
Insertion of element into the linear queue.
FIGURE 2.9
Removing an element from the linear queue.
44 Data Structures using C
Output:
FIGURE 2.10
Deletion operation in a linear queue.
Sequential Representation of Linear Data 47
only. Here in the above linear queue, if we try to insert any more elements,
then it won’t be possible as it will give “queue full” message. Although there
is space for elements 10, 20, 30, which is already deleted, we cannot utilize
this space because the type of queue is a linear queue.
Hence, to overcome the drawback of the linear queue, we will introduce
another type of queue called as a circular queue. The main advantage of the
circular queue is that we can utilize the space of a circular queue fully.
rear = (rear+1)%size
front = (front+1)%size
For example, in Figure 2.11, the size of the circular queue is 5, if rear points
to 4 index, and front points, to the index 3, then index 0, 1 and 2 places are
empty in the circular queue, and if we insert a new element in the circular
queue, then from rear end, we will insert it. In this situation, the rear is cal-
culated as
FIGURE 2.11
Circular queue.
48 Data Structures using C
Then, a new element is inserted into the circular queue at the rear index 0.
Let us consider that front is pointing to index 3. Similarly, while deleting
the element from the circular queue, front is calculated as,
Therefore, the element at the third position is deleted and the front gets
incremented to the fourth index and the front points to the fourth position
element in the circular queue.
Various operations on the circular queue are as follows:
1. Overfow operation
2. Underfow operation
3. Inserting the element into the circular queue is also called as enqueue
operation.
4. Removing an element from the circular queue is also called as
dequeue operation.
5. Display the elements of the circular queue.
Some of the important conditions we must know about the circular queue
are as follows:
1. If the rear and front points to the same index, then circular queue
consists of only one element.
2. If the front index is greater than one than the rear index, which means
if the front index is 4 and the rear index is 3, the circular queue is full.
If (front == (rear+1) % max size of the circular queue), if this condi-
tion is true, then and then only circular queue is full.
3. If front and rear index point to the −1, then the circular queue is said
to be empty (Figure 2.12).
In the above circular queue, if we want to insert a new item into the circular
queue, then increment the rear index as follows.
The current value of the rear index is 4 and the size of the circular queue
is 5, and then the rear index of the newly inserted element is computed as,
FIGURE 2.12
Enqueue and Dequeue operation on circular queue.
Sequential Representation of Linear Data 49
Therefore, insert the element at the rear index 0 in our circular queue. The
circular queue is not full because front is pointing to index 3. In this way, we
can utilize the deleted space in the circular queue.
// main function
int main()
{
int choice, data;
char ch;
front=-1;
rear=-1;
do
{
printf(" Circular Queue:");
printf(" 1:insert\t 2:delete\t 3:display\t 4.exit\n");
printf(" Enter your choice:");
scanf("%d", &choice);
switch(choice)
{
case 1:
printf("Enter data: ");
scanf("%d",&data);
if(qfull())
printf("\nqueue is full");
else
insert(data);
Sequential Representation of Linear Data 51
break;
case 2:
if(qempty())
printf("\n Circular queue is empty");
else
delete();
break;
case 3:
if(qempty())
printf("\n Circular queue is empty");
else
display();
break;
case 4:
exit(0);
default:
printf("\n Wrong choice");
}
printf(" Do you want to continue...[y/n]: ");
fflush(stdin);
scanf("%c",&ch);
}while(ch=='y');
return 0;
}
Output:
52 Data Structures using C
{
int data;
data=que[front];
front++;
printf(" Deleted element=%d \n", data);
}
//display element from priority queue
void display()
{
int i;
i=front;
printf("Elements in priority queue: ");
while(i<=rear)
{
printf("\t%d",que[i]);
i++;
}
printf("\n");
}
int main()
{
int choice, data;
char ch;
front=-1;
rear=-1;
do
{
printf(" Priority Queue");
printf(" 1:insert\t2:delete\t3:display\t4:exit");
printf("\n Enter your choice");
scanf("%d", &choice);
switch(choice)
{
case 1:
printf("Enter data: ");
scanf("%d",&data);
if(qfull())
printf("\n Queue is full");
else
insert(data);
break;
case 2:
if(qempty())
printf("\n Queue is empty");
else
delete();
break;
case 3:
if(qempty())
printf("\n Queue is empty");
else
Sequential Representation of Linear Data 55
display();
break;
case 4:
exit(0);
default:
printf("\n Wrong choice");
}
printf(" Do you want to continue[y/n]");
fflush(stdin);
scanf("%c",&ch);
}while(ch=='y');
return 0;
}
Output:
FIGURE 2.13
Input-restricted double-ended queue representation.
FIGURE 2.14
Output-restricted double-ended queue representation.
Sequential Representation of Linear Data 57
display();
break;
case 3: value=deQueueFront();
printf("\nThe value deleted
from front end of Dequeue is %d",value);
display();
break;
case 4: display();
break;
default:printf("Wrong choice");
}
printf("\nDo you want to continue
another operation (Y/N): ");
ch=getche();
}while(ch=='y'||ch=='Y');
getch();
break;
case 2 :
printf("\nSelect the Operation:\n");
printf("1. Insert at Rear\n2. Insert at
Front\n3. Delete from Front\n4. Display");
do
{
printf("\nEnter your choice for the
operation: ");
scanf("%d",&choice2);
switch(choice2)
{
case 1: enQueueRear(value);
display();
break;
case 2: enQueueFront(value);
display();
break;
case 3: value = deQueueFront();
printf("\nThe value deleted
from front end of Dequeue is %d",value);
display();
break;
case 4: display();
break;
default:printf("Wrong choice");
}
printf("\nDo you want to continue
another operation (Y/N): ");
ch=getche();
} while(ch=='y'||ch=='Y');
getch();
break ;
Sequential Representation of Linear Data 59
}
printf("\nDo you want to continue (Y/N):");
ch=getch();
}while(ch=='y'||ch=='Y');
}
Output:
Stack Queue
The stack is a non-primitive linear data The queue is also a non-primitive linear data
structure. structure.
The stack is implemented using basic The queue is also implemented using basic data
data structures such as an array or structures such as an array or linked list.
linked list.
The stack is a linear data structure in The queue is a linear data structure in which
which elements are inserted and deleted elements are inserted from one end called a rear
from only one end called top of the stack end and removed from the other end called the
and is based on the LIFO principle. front end and is based on the FIFO principle.
(Continued)
Sequential Representation of Linear Data 63
Stack Queue
Adding and removing of elements are Adding and removing of elements are carried out
carried out from only one end in the from different ends in the queue.
stack.
Inserting an element on the stack is Insert operation in the queue is called enqueue.
called push operation.
Deleting an element from the stack is Remove element operation in the queue is called
called pop operation. as dequeue operation.
In the Stack data structure, only one The queue data structure needs two pointers in
pointer is maintained, which is pointing their implementation, pointing to the rear end
to the top element of the stack. and pointing to the front end.
The stack data structure is an iterative The queue is a sequential data structure and is
data structure and is used to resolve used for troubleshooting issues involving
problems based on recursion. sequential processing.
The stack can be used to solve issues like Producer consumer problems are addressed using
pre-order, post-order and in-order a queue data structure as the underlying data
traversal of a binary tree. structure.
Stack data structure can be considered as The queue data structure can be considered as a
a vertical linear collection. horizontal linear collection.
The collection of plates placed above People standing in a queue to pay the electricity
each other is a specifc real-world bill or take a ticket from the movie counter are
example of the stack. the specifc real-world example of a queue.
17. Suppose the numbers 0, 1, 2,…, 9 were pushed onto a stack in that
order but that pops to occur at random points between the various
pushes. The following is a valid sequence in which the values in the
stack could have been popped:
3, 2, 6, 5, 7, 4, 1, 0, 9, 8
Explain why it is not possible that
3, 2, 6, 4, 7, 5, 1, 0, 9, 8 is a valid sequence in which the values could
have been popped off the stack.
18. Consider an empty stack of integers. Let the numbers 1, 2, 3, 4, 5
and 6 be pushed onto this stack only in the order they appeared
from left to right. Let S indicate a push and X indicate a pop
operation. Can they be permuted into order 325641 (output) and
order 154623? (if a permutation is possible, give the order string of
operations).
(Hint: SSSSSSXXXXXX outputs 654321)
19. How to implement two stacks using only one array. Your stack prac-
tices must not indicate an overflow unless every slot in the array is
used?
20. How to implement stack using two queues?
Sequential Representation of Linear Data 65
Answer: (D)
2. Which of the following is not the type of queue data structure?
A. Priority queue
B. Circular queue
C. Single-ended queue
D. Ordinary queue
Answer: (C)
3. Which of the following data structure is non-primitive linear data
structure?
A. Stack
B. Graph
C. Trees
D. Binary tree
Answer: (A)
4. Which of the below is true about stack implementation using a
linked list?
A. In a push operation, if new nodes are inserted at the beginning
of the linked list, then in pop operation, nodes must be deleted
from the end.
B. In a push operation, if new nodes are inserted at the end of the
linked list, then in pop operation, nodes must be deleted from
the beginning.
C. Both of the above are true.
D. None of the above is true.
Answer: (D)
66 Data Structures using C
Answer: (A)
6. Which of the following statements is false or true?
A. The stack is a non-primitive linear data structure.
B. The queue is a primitive nonlinear data structure.
A. Statement 1 is false
B. Statement 2 is false
C. Statements 1 and 2 are false
D. Statements 1 and 2 are true
Answer: (B)
Explanation:
The queue is a non-primitive linear data structure.
7. The seven elements A, B, C, D, E, F and G are pushed onto a stack in
reverse order, that is, starting from G. The stack is popped fve times,
and each element is inserted into a queue. Two elements are deleted
from the queue and pushed back onto the stack. Now, one element is
popped from the stack. The popped item is ________.
A. A
B. B
C. F
D. D. G
Answer: (B)
8. Which of the following is an application of non-primitive linear
queue data structure?
A. When a resource is shared among multiple consumers?
B. When data is transferred asynchronously between two processes?
C. Load balancing
D. All of the above
Answer: (D)
Sequential Representation of Linear Data 67
Answer: (D)
10. Which of the following statements is false or true?
A. In the DFS graph, the traversing technique queue data structure is
used.
B. In expression evaluation, the stack data structure is used.
A. Statement 1 is false
B. Statement 2 is false
C. Statements 1 and 2 are false
D. Statements 1 and 2 are true
Answer: (A)
Explanation:
In the DFS graph, the traversing technique stack data structure is used.
11. Stack cannot be used to
A. Implement recursion
B. Arithmetic expression evaluation
C. Parsing or syntax analysis
D. In CPU scheduling and disk scheduling.
Answer: (D)
Explanation: Stack can be used to solve arithmetic expression,
implementing recursion and parsing. While queue is useful in CPU
scheduling and disk scheduling.
12. A single array A[1..MAXSIZE] is used to implement two stacks. The
two stacks grow from opposite ends of the array. Variables top1 and
top2 (topl< top 2) point to the location of the topmost element in each
of the stacks. If the space is to be used effciently, the condition for
“stack full” is (GATE CS 2004)
A. (top1 = MAXSIZE/2) and (top2 = MAXSIZE/2+1)
B. top1 + top2 = MAXSIZE
68 Data Structures using C
Answer: (D)
Explanation
If we want to use space effciently, then the size of any stack can be
more than MAXSIZE/2. Both stacks will grow from both ends, and
if any of the stack top reaches near the other top, then stacks are full.
Therefore, the condition will be top1 = top2 -1 (given that top1 < top2)
13. Which one of the following is an application of stack data structure?
A. Implement recursion
B. Towers of Hanoi problems
C. Arithmetic expression evaluation
D. All of the above
Answer: (D)
14. The postfx form of the expression (A+ B)*(C*D- E)*F / G is?
A. AB+ CD*E - FG /**
B. AB + CD* E - F **G /
C. AB + CD* E - *F *G /
D. AB + CDE * - * F *G /
Answer: (A)
15. The non-primitive linear data structure required to check whether
an expression contains balanced parenthesis is
A. Stack
B. Queue
C. Array
D. Tree
Answer: (A)
16. If the elements “A”, “B”, “C” and “D” are placed in a stack and are
removed one at a time, in what order will they be deleted?
A. ABCD
B. DCBA
C. DCAB
D. ABDC
Answer: (B)
Sequential Representation of Linear Data 69
Answer: (B)
#define MAX 10
Struct STACK
{
Int arr [MAX];
Int top = -1;
}
If the array index starts with 0, the maximum value of top that
does not cause stack overfow is?
A. 8
B. 9
C. 10
D. 11
Answer: (A)
Answer: (D)
Push(1);
Pop();
Push(2);
Push(3);
Pop();
Push(4);
70 Data Structures using C
Pop();
Pop();
Push(5);
Answer: (A)
21. What is the name where deletion can be done in a linear list of ele-
ments from one end (front) and insertion can take place only at the
other end (rear)?
A. Queue
B. Stack
C. Tree
D. Linked list
Answer: (A)
22. Let the following circular queue can accommodate maximum six
elements with the following data
front = 2 rear = 4
queue = _______; L, M, N, ___, ___
Answer: (A)
23. If the MAX_SIZE is the size of the array used in the implementation
of the circular queue. How is rear manipulated while inserting an
element in the queue?
A. rear=(rear%1)+MAX_SIZE
B. rear=rear%(MAX_SIZE+1)
Sequential Representation of Linear Data 71
C. rear=(rear+1)%MAX_SIZE
D. rear=rear+(1%MAX_SIZE
Answer: (C)
A. Queue
B. Circular queue
C. Dequeue
D. Priority queue
Answer: (C)
void fun(int n)
{
IntQueue q = new IntQueue();
q.enqueue(0);
q.enqueue(1);
for (int i = 0; i < n; i++)
{
int a = q.dequeue();
int b = q.dequeue();
q.enqueue(b);
q.enqueue(a + b);
ptint(a);
}
}
A. Prints numbers from 0 to n-1
B. Prints numbers from n-1 to 0
C. Prints frst n Fibonacci numbers
D. Prints frst n Fibonacci numbers in reverse order.
Answer: (C)
Answer: (A)
Explanation:
Suppose we start flling the queue. Let the maxQueueSize that is
the capacity of the Queue is 4. Therefore, the size of the array that is
used to implement, this circular queue is 5, which is n.
In the beginning when the queue is empty, FRONT and REAR
point to 0 index in the array. REAR represents insertion at the REAR
index. FRONT represents deletion from the FRONT index.
enqueue("a"); REAR = (REAR+1)%5; ( FRONT = 0, REAR = 1)
enqueue("b"); REAR = (REAR+1)%5; ( FRONT = 0, REAR = 2)
enqueue("c"); REAR = (REAR+1)%5; ( FRONT = 0, REAR = 3)
enqueue("d"); REAR = (REAR+1)%5; ( FRONT = 0, REAR = 4)
(REAR+1) %n = (4+1) %5 = 0
FRONT is also 0.
Hence (REAR + 1) %n is equal to the FRONT.
When Queue Empty:
REAR was equal to FRONT when empty (because in the starting,
before filling the queue FRONT = REAR = 0)
Hence Option A is correct.
while (!isEmpty(&S))
{
// Pop an item from S and enqueue the poppped item to Q
enQueue(Q, pop(&S));
}
}
What does the above function do in general?
A. Removes the last from Q
B. Keeps the Q the same as it was before the call
C. Makes Q empty
D. Reverses the Q
Answer: (D)
A. Queue
B. Circular queue
C. Dequeue
D. Priority queue
Answer: (C)
29. A circular queue is implemented using an array of size 10. The array
index starts with 0, the front is 6, and the rear is 9. The insertion of
the next element takes place in the array index.
A. 0
B. 7
C. 9
D. 10
Answer: (A)
Answer: (B)
31. Consider the following pseudo-code. Assume that IntQueue is an
integer queue. What does the function fun do?
Answer: (C)
3
Void Pointer and Dynamic
Memory Management
Syntax:
void * vptr;
DOI: 10.1201/9781003105800-3 75
76 Data Structures using C
*((type *)vptr);
Typecast
Dereferencing operator
Output:
x = 100
y = 50.50
Output:
The value of integer variable a = 21
The value of float variable b = 21.21
A void pointer may be useful if the programmer is not sure which type of
data the end user has entered. In such a case, the programmer may use a void
pointer to indicate the location of the unknown data type. The program can
be set in such a way to ask the user to inform the type of data and typecast-
ing can be carried out according to the information entered by the user. The
following is a code snippet.
Another important point you need to keep in mind about void pointers is
that pointer arithmetic cannot be performed on a void pointer.
Example:
void *ptr;
int a;
78 Data Structures using C
ptr=&a;
ptr++;
This statement is invalid and will result in an error because ‘ptr’ is a void
pointer variable, and we cannot increment it.
3.1.4 Important Point
3.1.4.1. NULL versus uninitialized pointer: An uninitialized pointer
stores an undefined value. A null pointer stores a defined value that
is zero or NULL address.
3.1.4.2. NULL versus void pointer: Null pointer is a value that stores
zero or NULL address, while the void pointer is a data type.
#include <stdio.h>
struct student
{
char name [10];
int roll_no;
} stud;
int main ()
{
struct student *pt;
pt=&stud;
printf(“Enter roll number \n”);
scanf(“%d”,&stud.roll_no); //or scanf(“%d”,&
pt->roll_no);
printf(“Enter name \n”);
scanf(“%s”, stud.name); //or scanf(“%s”,pt->name);
printf(“\n Accessing student structure data members using
pointer variable ”);
printf(“\n Name: %s Roll Number: %d ”, pt→name, pt→roll_no);
return 0;
}
Output:
Enter roll number
21
Void Pointer and Dynamic Memory Management 79
Enter name
xyz
Accessing student structure data members using pointer variable
Name: xyz Roll Number: 21
Note: -> (arrow operator) is used to access the structure’s data member,
using the structure’s pointer type variable.
Instead of pt->name we can also use (*pt).name.
Here parentheses around *pt are necessary because the dot operator ‘.’ has
a higher precedence than ‘*’. If we write *pt.name, it will raise the syntactical
error.
#include <stdio.h>
struct student
{
char name[10];
int * roll_no; //structure’s pointer type data member
} stud;
int main()
{
int a=21;
struct student *pt; // structure’s pointer type variable
pt=&stud;
pt->roll_no =&a;
printf(“Enter roll number \n”);
scanf("%d",&(*(pt->roll_no)));
printf(“Enter name \n”);
scanf("%s", pt->name);
printf(“\n Accessing student structure data members using
structure’s pointer variable ”);
printf(“\n Name: %s Roll Number: %d ”, pt->name,
*(pt->roll_no));
return 0;
}
Output:
Enter roll number
21
Enter name
xyz
Accessing student structure data members using structure’s pointer
variable
Name: xyz Roll Number: 21.
80 Data Structures using C
#include <stdio.h>
struct student
{
char name[10];
int roll_no;
} stud[2]={{"amol",21},{"suraj",31}};
int main()
{
struct student *pt;
pt=&stud[0];
printf("\n Accessing student structure roll number using
++pt->roll_no: ");
++pt->roll_no;
/* first pointer pt fetch the value of roll number and then
increment the roll number so output is 22 */
printf("\n Roll Number = %d",pt->roll_no);
printf("\n Accessing student structure roll number using
(++pt)->roll_no: ");
(++pt)->roll_no;
/* first address stored in pointer pt increment and then shows
value of roll number so output is 31 */
printf("\n Roll Number = %d",pt->roll_no);
return 0;
}
Output:
Accessing student structure roll number using ++pt->roll_no:
Roll Number = 22.
Accessing student structure roll number using (++pt)->roll_no:
Roll Number = 31.
Explanation:
++pt→roll_no;
Here first calculate the pt->roll_no value and then that roll number value
gets incremented. Therefore, pt->roll_no value is 21 then incremented by 1 so
it becomes 22.
However (++pt) →roll_no;
Increment pt first means increment address by 1 means one location and
then gives the count structure data member’s value at that address location
which is 31.
Function Task
malloc The malloc () function allocates requested size in bytes for single element
and returns a pointer to first byte of allocated space and initial element
value is garbage.
calloc The calloc () function assigns space for an array of elements, initializes them
to zero and returns a pointer to the first byte of allocated space.
free The free () function releases the space previously assigned by the malloc (),
calloc () or realloc () function.
realloc The realloc () function alters the size of the space already assigned.
char *cptr;
cptr=(char*) malloc (10);
Allocates 10 bytes of space for characters and store address of first byte in the
pointer cptr pointer variable, this is illustrated as:
100
cptr
#include <stdio.h>
#include <stdlib.h>
#include<string.h>
Let us compile and run the above program, this will produce the following
result:
Output:
String = Amol Jagtap, Address = 355090448
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
Output:
Enter a line of text.
Hello students.
Hello students.
Enter another line of text.
Welcome to our class.
Hello students. Welcome to our class.
3.4 Memory Leakage
A memory leak occurs when a programmer creates a memory dynamically
on heap partition and forget to delete it. Here memory allocated at the time of
compilation is removed by the runtime environment based on the variable’s
lifetime. However, memory allocated dynamically is not deleted automati-
cally, for that purpose programmer must write code for that, in C language
free () function is used for releasing dynamically allocated memory.
{
fun();
return 0;
}
Here, in the function, fun, memory allocated dynamically for int but which
is not releasing so that memory on heap remains allocated after the total
execution of the program. For that purpose, free function is used. To avoid
memory leaks, memory allocated on the heap must always be freed when no
longer needed.
3.5 Dangling Pointer
A dangling pointer points to a memory location that has previously been
freed. Storage is not available anymore. Trying to access that memory can
cause a segmentation error or can crash the program.
The pointer can act as a dangling pointer in three ways, which are explained
below:
#include <stdio.h>
int main()
{
int *ptr = (int *)malloc(sizeof(int));
/* After free function call, pointer ptr becomes a dangling
pointer because dynamically allocated memory to ptr becomes
free and ptr points to that memory location on heap which is
not allocated. */
free(ptr);
// Assign NULL address to ptr pointer, now ptr pointer is not
a dangling pointer.
ptr = NULL;
return 0;
}
3.5.2 Function Call
The pointer pointing to local variable becomes dangling when a local vari-
able is non-static and which returns the address to another function.
#include <stdio.h>
int * sample()
{
/* x is a local variable and goes out of scope and variable
becomes dead after execution of sample() function is over. */
int x = 21;
return &x;
}
int main ()
{
int *p = sample ();
fflush(stdin);
// p points to something which is not valid anymore.
printf("%d", *p);
return 0;
}
Output:
Segmentation Fault
As runtime error.
The solution to this problem:
The pointer pointing to local variable does not become dangling when a
local variable is static.
#include <stdio.h>
int * sample()
{
Void Pointer and Dynamic Memory Management 87
Output:
21
Here ptr pointer is dangling pointer because after block1 variable i value
becomes dead and also variable i’s scope is over. That is again pointer ptr
stores address of freed variable. Therefore, ptr becomes dangling after
block1’s execution is over.
3.6 Interview Questions
1. What is the use of void pointer?
2. Explain the generic pointer with a suitable example.
3. Differentiate between the void pointer, NULL pointer and an unini-
tialized pointer.
88 Data Structures using C
Answer: (A)
Explanation:
Heap memory partition is used for dynamic memory management.
4. Which method is used to remove the dynamically allocated memory
space?
A. dealloc() function
B. free() function
C. realloc() function
D. Both A and B
Answer: (B)
Explanation:
free() method is used to release the memory space allocated on
heap partition by malloc() and calloc() functions.
5. Which of the following is correct function declaration for malloc()
function in C language?
A. void * malloc ( int size_t)
B. char* malloc (char )
C. int * malloc (int size_t)
D. float * malloc ( float size_t)
Answer: (A)
Explanation:
malloc() function having return type as void * and argument to
the malloc() function is size in integer.
6. Which functions are used for memory allocation at runtime in C
language?
A. malloc() function
B. calloc ( ) function
C. realloc () function
D. Both A and B
Answer: (D)
Explanation:
90 Data Structures using C
#include <stdlib.h>
#include<stdio.h>
void fun()
{
int *ptr = (int *) malloc(sizeof(int));
printf(“\n Memory allocated dynamically for integer
variable”);
}
int main()
{
fun();
return 0;
}
A. Memory Leakage
B. Dangling pointer
C. Compiler error
D. None of the the above
Answer: (A)
Explanation:
The problem is memory leakage, pointer ptr is allocated some
memory which is not freed meaning that what remains allocated on
the heap memory partition causes memory leakage.
int y;
int main()
{
int z = 0;
int *x = int * malloc( sizeof(int));
}
Answer: (A)
Explanation:
For x variable. dynamic memory gets reserved so it is allocated on
the heap memory partition. While y is global variable and stored on
global partition of the RAM. z is a local variable and stored on stack
partition of the RAM.
11. In realloc() library function, if the new size of the memory block is
greater than the old size, then newly added memory space …..?
A. is initialized to one
B. is initialized to zero
C. is not initialized
D. none of the above
92 Data Structures using C
Answer: (C)
Explanation:
In realloc() library function, newly added space is not initialized.
13. The free() function frees the memory allocated at runtime and
returns _____
A. pointer value
B. the memory address of the freed variable
C. no value is return
D. an float value is return
Answer: (C)
Explanation:
Free function having return type as void means it does not return
any value.
14. Which of the following function allocates requested size of bytes for
single element and returns a pointer to first byte of allocated space at
runtime and initial element value is garbage.
A. calloc() function
B. malloc() function
C. realloc() function
D. None of the above
Answer: (B)
Explanation:
malloc() function allocates memory dynamically and returns an
address of first byte and initial element value is garbage.
Void Pointer and Dynamic Memory Management 93
15. Which of the following pointer stores a defined value that is zero or
NULL address.
A. NULL pointer
B. void pointer
C. Dangling pointer
D. None of the above
Answer: (A)
Explanation:
Null pointer is a value that stores zero or NULL address.
Answer: (D)
Explanation:
A dangling pointer points to a memory location that has previ-
ously been freed and a memory leak occurs when a programmer cre-
ates a memory dynamically on heap partition and forget to delete it.
DOI: 10.1201/9781003105800-4 97
98 Data Structures using C
FIGURE 4.1
Structure of node and linked list of integers.
Linked Representation of Linear Data Structures 99
struct node
{
int data;
struct node *next;
};
Using the above declaration syntax, we can create a number of nodes having
integer data and the next pointer stores the address of the next node in the
linked list.
#include<stdio.h>
#include<conio.h>
struct node //structure for a node
{
int data;
100 Data Structures using C
Output:
10
20
30
Explanation:
Step 1: Declare the nodes n1, n2 and n3 in the structure type (Figure 4.2).
Step 2: Start flling data into each node in the data feld and assigning the
address of the next node to the next pointer feld of the node.
Here, node n2’s address is 200 and is assigned to the next feld of node n1,
which is shown in Figure 4.3.
FIGURE 4.2
Structure of node in a linked list.
Linked Representation of Linear Data Structures 101
FIGURE 4.3
Insertion of data and address in a node.
FIGURE 4.4
Linked list contains three nodes with data and address of next node.
Similarly, add 20 data in the data feld and address of the n3 node to the n2
node’s next feld and 30 data to the n3 node and the last node’s link or next
feld contains a NULL address assigned using the statement, n3. next=NULL;
Step 3: Set
first=&n1;
temp=first;
{
printf(“%d”, temp->data);
temp=temp->next;
}
Here, temp ->next is the address of the next node in the linked list.
When the temp pointer points to the last node, then temp->next value is
NULL which is assigned to temp by using above statement
temp=temp->next ;
And then while (temp != NULL)
• Singly because node consists of only one link part that is next which
stores address of the next node.
• Linear because the last node points to nothing means last node’s next
or link feld contains a NULL address.
• The frst node is called the head or the frst node (Figure 4.5).
• Circular means the last node’s link or next feld points to the frst or
head node or contains the address of the frst node.
• That is last node n3’s next feld contains the address 100 of frst node
containing data 10 (Figure 4.6).
FIGURE 4.5
Singly linear linked list.
FIGURE 4.6
Singly circular linked list.
Linked Representation of Linear Data Structures 103
FIGURE 4.7
Doubly linear linked list.
FIGURE 4.8
Doubly circular linked list.
• Doubly because each node has two pointers previous and next
pointers.
• The previous pointer points to the previous node and the next
pointer points to the next node or contains the address of next
node.
• Only the head node’s previous pointer feld contains NULL and the
last node’s next pointer points to a NULL address (Figure 4.7).
• In a circular doubly linked list, the next pointer of the last node
points to the previous pointer of head and the previous pointer of
the head node points to the next pointer of the last node.
• The head node is a special node that may have either dummy data
or some useful information, such as the total number of nodes in the
list (Figure 4.8).
temp->next != NULL .
4.4.1.2 Algorithm: Delete a Node from the Singly Linear Linked List
Step 1: [check for under fow]
Step 2: Read the information which you want to delete, say ‘num’.
Go on checking the data feld of each node, whether it matches ‘num’,
temp =temp->next;
}
}
Step 3: If found == 0
then print “No such number in the linked list” .
Step 4: If the node is found, then store that found the node address into a
temp pointer. If the found node is the frst node that is, temp == start, then
simply move start one position ahead and remove temp node.
start = start->next ;
temp->next = NULL;
free(temp);
Step 5: Else node found is other than frst node, then another pointer called as
prev is point to the previous node of temp node which you want to delete as
prev=start;
while(prev->next != temp)
{
prev = prev->next;
}
Then
prev->next=temp->next;
That is pointer prev’s next part (prev->next) points to the ‘temp’ node’s
(found node’s) next part & make temp->next=NULL (i.e. ‘temp’ node cannot
point to any other node) then the memory allocated for that ‘temp’ node is
deleted by free(temp) function.
temp=start;
while(temp!=NULL)
{
printf(“%d ”,temp->data);
temp=temp->next;
}
106 Data Structures using C
void create_node()
{
//allocate dynamic memory for a single node
new1=(struct node*)malloc(sizeof(struct node));
printf("Enter data : ");
scanf("%d",&new1->data);
new1->next=NULL;
if(start==NULL) //If Linked List is empty
{
start=new1;
}
else //If Linked List having at least one node
{
temp=start;
while(temp->next!=NULL) //traverse the list until
last node reached
{
temp=temp->next;
}
temp->next=new1;
}
printf("Node inserted at the end of Linked list=%d
\n",new1->data);
}
//display nodes in Singly Linear Linked List
void display()
{
if(start==NULL)
{
printf("Linked list is not created.\n");
}
else
{
temp=start;
printf("Data in the Singly Linear Linked List is as follows:
\n");
while(temp!=NULL)
{
printf("%d \t",temp->data);
temp=temp->next;
}
printf("\n");
}
}
//delete a node from a Singly Linear Linked List
void delete_node()
{
int num;
int found=0;
temp=start;
108 Data Structures using C
}
if(found == 0) // If node is not found
{
printf("\n Node is not present in the Linked List. \n");
}
else
{ //If node is found then node which we want to
delete is first // node or other than first node.
if(start == temp) //If deleted node is First node in
Linked List
{
start = start->next;
temp->next=NULL;
free(temp);
temp=NULL;
}
else //If deleted node is other than first node in
Linked List
{
prev=start;
while(prev->next!=temp)
{
prev=prev->next;
}
prev->next=temp->next;
temp->next=NULL;
Linked Representation of Linear Data Structures 109
free(temp);
temp=NULL;
}
printf("Node deleted =%d\n",num);
}
}
}
Output:
i. Creation
ii. Display
iii. Deletion
FIGURE 4.9
Create a node in the singly circular linked list.
FIGURE 4.10
Insert frst node in the singly circular linked list.
FIGURE 4.11
Insert second node in the singly circular linked list.
If fag=1 or start pointer contains a NULL address that means the newly
created node is the frst node in a circular linked list, then assign address of
the new node to the pointer start and the new node’s next contains address of
frst node means same node points to itself. Here new node is the frst node in
a circular linked list, then the frst node’s next feld stores address of the frst
node that is 100 and set fag=0 means next time onwards we can insert new
node at the end of the circular linked list.
Step 2: Create new node and insert data as 30 in the data feld and insert
new node in previously created circular linked list as shown in Figure 4.11.
Here, store the address of the new node into the new pointer of the circular
linked list and the address of the start node is stored in the new node’s next
feld. Thus, the new node is inserted into the circular lined list.
FIGURE 4.12
Singly circular linked list containing three nodes.
do
{
printf(“%d”,temp->data);
temp=temp->next;
}while(temp!=start);
FIGURE 4.13
Delete node from circular linked list containing only one node.
112 Data Structures using C
FIGURE 4.14
Delete frst node from circular linked list containing three nodes.
FIGURE 4.15
Delete any node other than frst node from circular linked list containing three nodes.
Linked Representation of Linear Data Structures 113
void delete_node();
void display();
{
start=new1;
new1->next=start;
flag=0;
}
else
{
temp=start;
while(temp->next!=start)
{
temp=temp->next;
}
temp->next=new1;
new1->next=start;
}
printf("Node inserted at the end of Linked list=%d
\n",new1->data);
}
temp=start;
printf("Enter data which you delete: ");
scanf("%d",&num);
//Singly Circular Linked List contain only one node and
deleted node’s value is matched with //entered value
if((start->next==start)&&(num==start->data))
{
temp->next=NULL;
start=NULL;
free(temp);
flag=1;
return;
}
//Singly Circular Linked List contain only one node and
deleted node’s value is not matched //with entered value
if((start->next==start)&&(num!=start->data))
{
printf("\n Node is not in the Singly Circular Linked
List.\n");
return;
}
//when list contain more than one node then search element
which we want to delete and //store that node’s address into
temp pointer.
do
{
if(temp->data==num)
{
found=1;
}
else
{
temp=temp->next;
}
}while((found==0)&&(temp!=start));
if(found==0) // If node not found
{
printf("\n Node is not in the Singly Circular Linked List.\n
");
}
else //If node is found
{
//If found node is first node in Singly Circular Linked List
then
if(temp==start)
{
start=start->next;
new1->next=start; //Here new1 contains address of last
node in the Singly Circular Linked temp->next=NULL; //
List because new node inserted at the end of linked list
free(temp);
116 Data Structures using C
temp=NULL;
}
// If found node is other than first node in Singly Circular
Linked List then
else
{
prev=start; //prev pointer stores address of first node
initially
while(prev->next!=temp) // after execution of while loop
prev pointer stores address of
{ //previous
node which we want to delete
prev=prev->next;
}
if(temp == new1) // if node deleted is last node in linked
list then store the address of prev
{ //pointer into new1 because new1 pointer contains
address of last node
new1= prev;
}
prev->next=temp->next;
temp->next=NULL;
free(temp);
temp=NULL;
}
printf("Node deleted =%d \n",num);
}
}
}
Output:
Linked Representation of Linear Data Structures 117
struct node
{
struct node *prev;
int data;
struct node *next;
};
FIGURE 4.16
Node in doubly linear linked list.
FIGURE 4.17
Doubly linear Linked list contains only one node.
FIGURE 4.18
Doubly linear linked list with three nodes.
118 Data Structures using C
Step 2: For further addition of nodes, a new node is created and inserted at
the end of the list (Figure 4.19).
Step 3: For further addition, a new node is created and inserted at the end
of the list as shown below.
First, search the last node in the list using code and store the address of the
last node in temp pointer (Figure 4.20):
FIGURE 4.19
Insert second node in doubly linear linked list at the end.
FIGURE 4.20
Insert third node in doubly linear linked list at the end.
Linked Representation of Linear Data Structures 119
if(temp==start)
{
start=start->next;
temp->next=NULL;
start->prev=NULL;
free(temp);
}
Step 3: If we want to delete node other than the frst node, then, here sup-
pose node 20 is to be deleted using the following code:
temp pointer contains the address of the node which we want to delete.
If temp pointer contains the address other than frst pointer, then node
which we want to delete is other than frst node in the doubly linear
linked list.
Then, assign the address of temp node’s next address to the temp node’s
previous node’s next feld using, (temp->prev)->next=temp->next;
Then, assign the address of temp node’s previous address to the temp node’s
next node’s previous feld using, (temp->next)->prev=temp->prev;
FIGURE 4.21
Delete a start node from doubly linear linked list.
120 Data Structures using C
FIGURE 4.22
Delete any node other than a start node from doubly linear linked list.
Then remove the links between temp and next node and temp and pre-
vious node using,
temp->next=NULL;
temp->prev=NULL;
Then de-allocate memory that is reserved for temp node using,
free(temp);
Here, dynamically reserved memory on heap get de-allocated and assign
temp=NULL means temp pointer does not point to de-allocated loca-
tion and dangling pointer problem is resolved (Figure 4.22).
temp=NULL ;
void create_node()
{
//allocate dynamic memory for a node on heap partition on RAM
new1=(struct node *)malloc(sizeof(struct node));
printf("Enter data: ");
scanf("%d",&new1->data);
new1->next=NULL;
new1->prev=NULL;
// doubly linear linked list is empty
if(start==NULL) // or if(flag==1)
{
start=new1;
flag=0;
}
// doubly linear linked list contains more than one node
else
{
temp=start;
while(temp->next!=NULL)
{
temp=temp->next;
}
temp->next=new1;
new1->prev=temp;
}
printf("Node inserted at the end of Linked list=
%d\n",new1->data);
}
//display data part in doubly linear linked list
void disp()
{
temp=start;
// doubly linear linked list is empty
if(start==NULL)
{
printf("\n Doubly linear linked list is empty.\n");
return;
}
else
{
printf("Data in the Doubly Linear Linked List is as follows:
\n");
while(temp!=NULL)
{
printf("\t%d",temp->data);
temp=temp->next;
}
printf("\n");
}
}
122 Data Structures using C
start->prev=NULL;
free(temp);
temp=NULL;
}else //doubly linear linked list contains only one node
and we want to delete is first node
{
free(temp);
start=NULL;
}
}
//Node which we want to delete is other than first node in
the doubly linear linked list
else
{
if(temp->next!=NULL) // Node deleted is not last node in
the doubly linear linked list
{
(temp->prev)->next=temp->next;
(temp->next)->prev=temp->prev;
}else // Node deleted is last node in the doubly
linear linked list
{
(temp->prev)->next=NULL;
}
temp->next=NULL;
temp->prev=NULL;
free(temp);
temp=NULL;
}
printf("Node deleted =%d \n",num);
}
}
} // end of delete_node function
//main function
int main()
{
int choice;
char ch;
start=NULL;
printf("Doubly linear linked list: ");
do
{
printf("1. create\t2. display\t3. delete\t4. exit");
printf("\n Enter your choice: ");
scanf("%d",&choice);
switch(choice)
{
case 1:create_node();
break;
case 2:disp();
124 Data Structures using C
break;
case 3:delete_node();
break;
case 4:exit(0);
default:printf("\n Wrong choice");
}
fflush(stdin);
printf("Do you want to continue[y/n]");
scanf("%c",&ch);
}while(ch=='y');
return 0;
}
Output:
4.6.3 Insert New Node at the Start of Doubly Linear Linked List
void insert_at_start()
{
new1=(struct node*)malloc(sizeof(struct node));
printf("\n Enter data in new node:");
scanf("%d",&new1->data);
new1->next=NULL;
new1->prev=NULL;
if(start==NULL)
{
start=new1;
}
else
{
new1->next=start;
start->prev=new1;
Linked Representation of Linear Data Structures 125
start=new1;
}
display(); // display all the node data from start node to
end of linked list.
}
{
temp=start;
while(temp!=NULL) //count number of nodes present in your
linked list
{
temp=temp->next;
count++;
}
lable1:
printf("\n Enter position to insert new node:"); //position
must be greater than zero
scanf("%d",&pos);
if( pos > (cont+1))
{
printf("\n Your choice is wrong");
goto lable1;
}
if(pos==1) //if node inserted at first position in doubly
linear linked list
{
start->prev=new1;
new1->next=start;
start=new1;
start->prev=NULL;
}
else // if node inserted at other than first
position in doubly linear linked list
{
temp=start;
while(i < (pos-1)) //traverse the temp pointer till temp
pointer contains address of previous
{ //node where we want to insert
the new node
temp=temp->next;
i++;
}
new1->next=temp->next;
temp->next=new1;
new1->prev=temp;
}
printf("\n Doubly linear linked list data:");
temp=start;
while(temp!=NULL) //display all nodes data from first node to
last node
{
printf("%d\t", temp->data);
temp=temp->next;
}
}
}
Linked Representation of Linear Data Structures 127
case 4:
display();
break;
default:
printf("\n You have entered wrong choice.\n");
}
fflush(stdin);
printf("Do you want to continue(Y/N): ");
scanf("%c",&ch);
}while(ch=='Y'||ch=='y');
return 0;
}
void display()
{
if(start==NULL)
{
printf("\n Doubly Circular Linked List is not created.\n");
return;
}
else
{
printf("Doubly Circular Linked List data:");
temp=start;
do
{
printf("%d\t",temp->data);
temp=temp->next;
} while(temp!=start);
printf("\n");
}
}
void insert_at_end()
{
new1=(struct node*)malloc(sizeof(struct node));
printf("Enter data in node: ");
scanf("%d",&new1->data);
new1->next=NULL;
new1->prev=NULL;
if(start==NULL)
{
start=new1;
start->next=start;
start->prev=start;
}
else
{
temp=start;
do
{
temp=temp->next;
Linked Representation of Linear Data Structures 129
} while(temp->next!=start);
temp->next=new1;
new1->prev=temp;
new1->next=start;
start->prev=new1;
}
display();
}
//display data in the doubly circular linked list in reverse
order
void reverse()
{
if(start==NULL)
{
printf("\n Doubly Circular Linked List is not created.");
return;
}
else
{
temp=start;
do // Using do while loop we have to move temp
pointer at the last node
{ //Here use do while or while loop both works
correctly
temp=temp->next;
} while(temp->next!=start);
// Now after exit from do while loop temp pointer contains
address of last node of doubly //circular linked list
do
{
printf("\t%d",temp->data);
temp=temp->prev;
}while(temp!=start->prev); //display data field from last
node to first node in reverse order
printf("\n");
}
}
void delet()
{
int num,found=0;
if(start==NULL)
{
printf("Doubly Circular Linked List is not created.\n");
return;
}
else
{
printf("Enter value of node which you want to delete: ");
scanf("%d",&num);
130 Data Structures using C
//If linked list contains only one node and that matched with
node which we want to delete
if(start==start->next && num==start->data)
{
start->next=NULL;
start->prev=NULL;
free(start);
start=NULL;
printf("Node deleted is %d\n",num);
return;
}
//If linked list contains only one node and that not matched
with node which we want to //delete
if(start==start->next && num!=start->data)
{
printf("\n Data not present in Doubly Circular Linked List ");
return;
}
temp=start;
do
{
if(temp->data==num)
{
found=1;
}
else
{
temp=temp->next;
}
}while(found!=1 && temp!=start);
if(found==0) //if node is not found in Doubly Circular
Linked List
{
printf("\n Node is not present in Doubly Circular Linked List
");
return;
}
else //if node is found in Doubly Circular Linked List
{
if(temp==start) //if first node we want to delete from
Doubly Circular Linked List
{
last=start;
do
{
last=last->next;
}
while(last->next!=start);
start=start->next;
last->next=start;
Linked Representation of Linear Data Structures 131
start->prev=last;
temp->next=NULL;
temp->prev=NULL;
free(temp);
temp=NULL;
}
else //if other than first node we want to delete from
Doubly Circular Linked List
{
(temp->prev)->next=temp->next;
(temp->next)->prev=temp->prev;
temp->next=NULL;
temp->prev=NULL;
free(temp);
temp=NULL;
}
printf("Node deleted is %d\n",num);
}
}
}
Output:
FIGURE 4.23
Stack representation using linked list.
FIGURE 4.24
Push operation on stack using linked list.
C structure for stack using linked list (Figures 4.23 and 4.24):
struct stack
{
int data;
struct stack *next;
}*new1,*top,*temp;
#include<stdio.h>
#include<stdlib.h>
struct stack
Linked Representation of Linear Data Structures 133
{
int data;
struct stack *next;
}*new1,*top,*temp;
// top pointer stores address of top node in your stack.
// temp pointer stores temporary address of a node and used
for traversing purpose.
// new1 pointer stores the address of newly created node of
your stack.
void push();
int pop();
void display();
int main()
{
int ch, item;
char c;
top =NULL;
do
{
printf(" Stack implementation using linked list: \n");
printf(" 1.push 2.pop 3.display 4.exit");
printf("\n Enter your choice: ");
scanf("%d",&ch);
switch(ch)
{
case 1:
push();
break;
case 2:
item=pop();
printf("Popped element from the stack=%d \n", item);
break;
case 3:
display();
break;
case 4:
exit(0);
default:
printf("\n wrong choice\n");
}
fflush(stdin);
printf("Do you want to continue(y/n):");
scanf("%c",&c);
} while(c=='y'||c=='Y');
return 0;
}
void push()
{
new1=(struct stack*)malloc(sizeof(struct stack));
printf("Enter data: ");
134 Data Structures using C
scanf("%d",&new1->data);
new1->next=NULL;
if(top == NULL)
{
top=new1;
}else
{
new1->next = top;
top = new1;
}
printf("Pushed element on stack is %d \n",new1->data);
}
int pop()
{
int data;
temp= top;
if(top==NULL)
{
printf("stack is underflow\n");
}
else
{
data= top ->data;
top = top ->next;
temp->next=NULL;
free(temp);
temp = NULL;
return(data);
}
}
void display()
{
temp=top;
if(top ==NULL)
{
printf("\n stack is empty");
}
else
{
while(temp!=NULL)
{
printf("\t %d",temp->data);
temp=temp->next;
}
printf("\n");
}
}
Linked Representation of Linear Data Structures 135
Output:
struct queue
{
int data;
struct queue *next;
}*new1,*rear,*front,*temp;
136 Data Structures using C
FIGURE 4.25
Linear queue representation using linked list.
//main() function
int main()
{
char ch;
int choice;
front=rear=NULL;
do
{
printf("Linear queue using linked list: ");
printf("\n 1.create 2.delete 3.display 4.exit: ");
printf("\n Enter choice: ");
Linked Representation of Linear Data Structures 137
scanf("%d", &choice);
switch(choice)
{
case 1:
create();
break;
case 2:
delet();
break;
case 3:
display ();
break;
case 4:
exit(0);
default:
printf("\n wrong choice");
}
fflush(stdin);
printf("Do you want to continue...[y/n]");
scanf("\n%c",&ch);
}while(ch=='y' || ch=='Y');
return 0;
}
temp=front;
if(front==NULL)
{
printf("\n Linear queue is empty");
return;
}
else
{
if( front == rear)
{
printf("Deleted element = %d \n", front->data);
front = NULL;
rear = NULL;
free(temp);
temp=NULL;
}else
{
printf("Deleted element = %d \n", front->data);
front=front->next;
temp->next=NULL;
free(temp);
temp=NULL;
}
}
}
//display linear queue elements from the front end to rear end
void display ()
{
temp=front;
if(front==NULL)
{
printf("\n Queue is empty");
}
else
{
printf("Data in linear queue is as follows: \n");
while(temp!=NULL)
{
printf("\t%d",temp->data);
temp=temp->next;
}
printf("\n");
}
}
Linked Representation of Linear Data Structures 139
Output:
Steps:
1. Create a new node dynamically and insert the data into the data
felds and next contains the address of NULL initially.
2. Verify if front==NULL, if it is true, then front = rear = address of
the newly created node.
3. If it is false, then rear = address of the newly created node and
front node always contains the address of the front node.
2. Dequeue operation: This operation or function is used to remove an
element from the circular queue. In a queue, the element is always
deleted from the front position.
Steps:
1. Check whether the queue is empty or not means front == NULL.
2. If it is empty then displaying queue is empty. If the queue is not
empty, then GOTO step 3.
3. Check if (front==rear) if it is true, then circular queue contains
only one node, then set front = rear = NULL else move the front
forward in the queue that is front=front->next. Display the
deleted element.
struct cqueue
{
int data;
struct cqueue *next;
}*new1,*rear,*front,*temp;
//front pointer stores the address of front or first node in
circular queue
//rear pointer stores the address of rear or last node in
circular queue
//new1 pointer stores the address of newly created node
//temp pointer stores the address of temporary node and used
for traversing purpose
FIGURE 4.26
Circular queue representation using linked list.
Linked Representation of Linear Data Structures 141
#include<stdio.h>
#include<stdlib.h>
//structure of circular queue using linked list
struct cqueue
{
int data;
struct cqueue *next;
}*new1,*rear,*front,*temp;
//function prototypes or function declaration
void create();
void delet();
void display();
//main() function
int main()
{
char ch;
int choice;
front=rear=NULL;
do
{
printf("Circular Queue using linked list: ");
printf("1.create 2.delete 3.display 4.exit");
printf("\n Enter choice: ");
scanf("%d", &choice);
switch(choice)
{
case 1:
create();
break;
case 2:
delet();
break;
case 3:
display ();
break;
case 4:
exit(0);
default:
printf("\n wrong choice:");
}
fflush(stdin);
printf("Do you want to continue...[y/n]");
scanf("%c", &ch);
}while(ch=='y' || ch=='Y');
return 0;
}
142 Data Structures using C
temp=NULL;
}
}
}
Output:
144 Data Structures using C
28. Write a C code for circular queue implementation using linked list?
29. Write a C code for stack implementation using linked list?
30. Implement C code for linear queue using linked list with a suitable
example.
31. Write C code for displaying all data members of singly linear linked
list in reverse manner.
32. Write an algorithm and C code for deleting any node from the singly
linear linked list.
q = NULL; p = head;
while (p-> next !=NULL) {
q=p;
p=p->next;
}
return head;
}
struct node {
int value;
struct node * next;
};
Void rearrange (struct node * list) {
Linked Representation of Linear Data Structures 147
struct node * p, * q;
int temp;
if (!list || !list -> next) return;
p = list; q = list -> next;
while (q) {
temp = p -> value; p -> value = q -> value;
q -> value = temp; p = q -> next
q = p? p -> next : 0;
}
}
A. 1,2,3,4,5,6,7
B. 2,1,4,3,6,5,7
C. 1,3,2,5,4,7,6
D. 2,3,4,5,6,7,1
Answer: (B)
Explanation:
4. Function rearrange takes list of integers as an input.
5. Inside function it checks condition to decide list is empty or with
single node. If condition is true then it returns head as it is with-
out modifcation.
6. Then, frst element will get assigned to p and second element to
q.
7. Inside while at frst iteration value of p and q will get swapped
means values of frst element and second element.
8. Then P modifed and points to third element.
9. If p is null then q holds 0 else q points to the 4th element
10. Means p points to odd number element and q points to even
number elements and then we are swapping their values.
11. So output will be 2,1, 4, 3, 6, 5, 7.
4. What does the following operation do for a given linked list with an
initial node as head?
Answer: (B)
Explanation:
1. In the above example, recursive function call is used.
2. printf statement is written after function call, so it will get exe-
cuted after returning from last function call.
3. Last function call will be to call func1 with null, so it will simply
return.
4. Second last function call will be with last node, so it will display
last node value.
5. In this way, linked list will get displayed in reverse order.
For Linked List 1->2->3->4->5, fun1() prints 5->4->3->2->1.
A. *head_ref = prev;
B. *head_ref = current;
C. *head_ref = next;
D. *head_ref = NULL;
Answer: (A)
Explanation:
*head_ref = prev;
At the end of while loop, the prev pointer points to the last node
of original linked list. We need to change *head_ref so that the head
pointer now starts pointing to the last node.
6. What is the result of the following function to start pointing to the
frst node of follow linked list?
1->2->3->4->5->6
void fun(struct node* start)
{
if(start == NULL)
return;
printf("%d ", start->data);
if(start->next != NULL )
fun(start->next->next);
printf("%d ", start->data);
}
A. 1 4 6 6 4 1
B. 1 3 5 1 3 5
C. 1 2 3 5
D. 1 3 5 5 3 1
Answer: (D)
Explanation:
In above example recursive function call is used:
Answer: (A)
Explanation:
Following are simple steps.
Linked Representation of Linear Data Structures 151
X->data = temp->data;
X->next = temp->next;
free(temp);
A. rear node
B. front node
C. not possible with a single pointer
D. node next to front
Answer: (A)
Explanation:
A. From rear node we can get front node so able to impement both
enQueue and deQueue with the help of rear.
B. From front we cannot access rear so we cannot perform both the
operations.
C and D. Not applicable
15. A linear collection of data elements where the linear node is given by
means of pointer is called?
A. Linked list
B. Node list
C. Primitive list
D. None
Answer: (A)
16. Which of the following operations is carried out more effciently by
the doubly-linked list than by the singly-linked list?
A. Deleting a node whose location in given
B. Searching of an unsorted list for a given item
C. Inverting a node after the node with given location
D. Traversing a list to process each node
Answer: (D)
A. I and II
B. I and III
C. I, II and III
D. I, II and IV
Answer: (B)
20. In singly linear linked list each node contains how many minimum
felds?
A. Five
B. Zero
C. Two
D. Four
Answer: (C)
Explanation:
In singly linear linked list, each node contains data feld and link
feld.
23. What is known as a linear collection of data items, where the each
node is given by means of a pointer to the next node?
A. Linked list
B. Node list
C. Primitive list
D. None of these
Answer: (A)
24. In singly linear linked list, each node contains minimum of two
felds. One feld is the data feld to store the data second feld. What
is it called as?
A. Pointer to character array
B. Pointer to integer
C. Node address
D. Pointer to next linked list node
Answer: (D)
25. Which of the following type of the linked list can be used so that
concatenation of two lists can give the time complexity as O (1)?
A. Singly linked list
B. Doubly linked list
C. Doubly circular linked list
D. Array implementation of list
Answer: (C)
28. Which of the following C language code is used to create a new node
in the singly linear linked list.
struct node
{
int data;
struct node * next;
}
typedef struct node LIST;
LIST*ptr;
31. Each node of a singly linear linked list must contain at least..…
A. Three felds
B. Two felds
C. Six felds
D. Five felds
Answer: (B)
36. Which of the following singly linear linked list representation using
C language is correct?
A.
struct node
{
int data;
struct node *next;
};
B.
struct node
{
int data;
struct node **next;
};
C.
struct node
{
int data;
struct node *next;
struct node *prev;
};
D.
struct node
{
int data;
int node *next;
};
Answer: (A)
A. Statement 1 is false
B. Statement 2 is false
160 Data Structures using C
struct node
{
struct node *prev;
int data;
struct node *next;
}; This is the node representation for Singly Linear
Linked List in C language.
2.
struct node
Linked Representation of Linear Data Structures 161
{
int data;
struct node *next;
}; This is the node representation for Doubly Linear
Linked List in C language.
Answer: (C)
5
Nonlinear Data Structures: Trees
FIGURE 5.1
Tree with seven nodes and six links or edges.
8. Degree:
In a nonlinear tree data structure, the total number of children of a
node is known as the degree of that node. Simply stated, the degree of
a node in a tree data structure is the total number of child nodes it has.
The highest degree of a node among all the nodes of a tree is
termed as ‘degree of tree’. In Figure 5.1, the degree of the C node is
3 and the degree of the B node is 1. However, the degree of tree is 3.
9. Level:
In a nonlinear tree data structure, the root node is stated to be at
Level 0 and the children of the root node are at Level 1 and the chil-
dren of the nodes which are at Level 1 will be at Level 2 and so on.
Simply stated, in a tree data structure, each step from top to bottom is
called a Level, and the Level count starts with ‘0’ and is incremented
by one at each level or step. In Figure 5.1, levels of D, E, F and G are 2.
10. Height:
In a nonlinear tree data structure, the total number of edges or
links from a leaf node to a specifc node in the longest path is called
as height of that node. In a tree, the height of the root node is said to
be the height of the tree. In a tree, the height of all leaf nodes is ‘0’.
In Figure 5.1, the height of the A node is 2 and the height of tree is
also 2.
11. Depth:
In a nonlinear tree data structure, the total number of edges from
the root node to a particular node is called the depth of that node. In
a tree, the total number of edges from the root node to a leaf node in
the longest path is said to be the depth of the tree. Simply stated, the
highest depth of any leaf node in a tree is said to be the depth of that
tree. In a tree, the depth of the root node is ‘0’.
In Figure 5.1, the depth of node D is 2 and the depth of a tree is also
2. The height and depth of a tree are equal, but the height and depth
of the node are not equal because the height is calculated by travers-
ing from a given node to the deepest possible leaf node. Depth is
calculated from traversing from root to the given node.
12. Path:
In a nonlinear tree data structure, the sequence of nodes and edges
from one node to another node is called a path between the two
nodes. The length of a path represents the total number of nodes on
that path. In Figure 5.1, path A - B - D has length 3.
13. Sub-tree:
In a nonlinear tree data structure, each child of a node forms a
subtree recursively. Each child node consists of a sub-tree with its
parent node.
14. Forest:
Forest is the disjoint union of trees.
166 Data Structures using C
FIGURE 5.2
Binary tree.
FIGURE 5.3
Two binary trees with two nodes.
Nonlinear Data Structures: Trees 167
FIGURE 5.4
Strictly binary tree or full binary tree or proper binary tree.
FIGURE 5.5
Complete binary tree.
is the frst strictly binary tree with the height difference of only 1
allowed between the left and right sub-tree. All leaf nodes are either at
the same level or only a difference of 1 level is permissible (Figure 5.5).
FIGURE 5.6
Binary search tree.
1. Each leaf node in the tree is either at level d or at level d-1, which
means the difference between levels of leaf nodes is only one is
permissible.
2. At depth d, that is the last level, if a node is present, then all the
nodes to the left of that node should also be present frst, and no gap
between the two nodes from the left to the right side of level d.
In Figure 5.7, nodes at the last level are flled from left to right, and
no gaps between the last level’s nodes. However, in Figure 8, the last
level, having two nodes H and I have one gap because D nodes left
child is present, but the right child is absent so Figure 5.8 is not an
almost complete binary tree.
Figure 5.7 shows almost a complete binary tree, but not a com-
plete binary tree because the D node has a left child but no right
child. In the complete binary tree, every interior node has exactly
two children.
5. Skewed binary tree:
If a tree is dominated by the left child node or the right child node,
it is said to be a skewed binary tree.
FIGURE 5.7
Almost complete binary tree.
Nonlinear Data Structures: Trees 169
FIGURE 5.8
Not an almost complete binary tree.
FIGURE 5.9
Left skewed tree.
FIGURE 5.10
Right skewed tree.
170 Data Structures using C
FIGURE 5.11
Complete binary tree.
FIGURE 5.12
Sequential representation of binary tree using array.
Nonlinear Data Structures: Trees 171
struct binary_tree
{
struct bt *left;
int data;
struct bt *right;
};
172 Data Structures using C
FIGURE 5.13
Node in the linked list representation.
However, from there three traversing methods are important, which are
as follows:
These all above traversing technique is also called as Depth First searching
(DFS) or Depth First Traversal.
A tree is typically traversed in two ways:
Algorithm
In a binary tree, the root node is visited frst, then its child nodes are visited
and enqueue in a queue. Then dequeue a node from the queue and fnd its
child nodes and again insert it into queue till all nodes are visited.
FIGURE 5.14
Binary tree traverse by using Breadth First Traversal or Level Order Traversal.
174 Data Structures using C
1. In-order traversal
2. Preorder traversal
3. Post-order traversal
FIGURE 5.15
Binary tree traverse by using in-order traversal method.
Nonlinear Data Structures: Trees 175
FIGURE 5.16
Binary tree traverse by using preorder traversal method.
FIGURE 5.17
Binary tree traverse by using post-order traversal method.
If the next node says 21, then users will be asked for his choice that is attached
to the left or right of 10. If the user answers left or l, then the tree will be,
176 Data Structures using C
Then, if the next element is 11, then again the user has to give his choice,
whether it is left or right. That means frst whether the user wants to attach
11 left or right of root 10. Then, if the user answers left, then again the user
asks whether the user wants to attach 11 to left or right of 21, and if the user
answers right, then node 11 will be attached as a right child of 21.
Thus, a simple binary will be generated. The principal idea behind this
creation is to always ask the user where he wants to attach the next node and
always start scanning the tree from the root.
Program: Implementation of simple binary tree and performing
recursive insertion and traversing operations on a simple binary tree.
#include<stdio.h>
#include<stdlib.h>
struct bt
{
struct bt *left;
int data;
struct bt *right;
};
// Function prototypes
void insert(struct bt *root, struct bt *new1);
void in-order(struct bt *temp);
void preorder(struct bt *temp);
void postorder(struct bt *temp);
// main function definition
Nonlinear Data Structures: Trees 177
int main()
{
struct bt *root, *new1;
int ch;
char c;
root=NULL;
do
{
printf("1. Create 2.In-order 3. Preorder 4. Postorder 5. Exit
\n");
printf("Enter your choice: ");
scanf("%d",&ch);
switch(ch)
{
case 1:
do
{
new1=(struct bt*)malloc(sizeof(struct bt));
printf("\n Enter data: ");
scanf("%d",&new1->data);
new1->left=NULL;
new1->right=NULL;
if(root==NULL)
{
root=new1;
}
else
{
insert(root,new1);
}
printf("\n Do you want to insert new node [y/n]: ");
c = getche();
}while(c=='y'||c=='Y');
break;
case 2:
if(root==NULL)
printf("\n Binary Tree is not created");
else
{
in-order(root);
}
break;
case 3:
if(root==NULL)
printf("Binary Tree is not created");
else
{
178 Data Structures using C
preorder(root);
}
break;
case 4:
if(root==NULL)
printf("Binary Tree is not created");
else
{
postorder(root);
}
break;
case 5:
exit(0);
default:
printf("\n wrong choice: ");
}
printf("\n Do you want to continue Binary Tree [y/n] : ");
fflush(stdin);
scanf("%c",&c);
}while(c=='y'||c=='Y');
return 0;
}
void insert(struct bt* root, struct bt *new1)
{
char c;
printf("\n Where to insert node right or left of %d : ",
root->data);
c=getche();
//if new node is to be inserted at right sub-tree
if(c=='r'||c=='R')
{
if(root->right==NULL) //if root node’s right pointer is
NULL then insert new node to
// right side
{
root->right=new1;
}
else // otherwise call insert function
recursively
{
insert(root->right,new1);
}
}
//if new node is to be inserted at left sub-tree
if(c=='l'||c=='L')
{
if(root->left==NULL)
Nonlinear Data Structures: Trees 179
{
root->left=new1;
}
else
{
insert(root->left,new1);
}
}
}
//in-order traversing of a simple binary tree
void in-order(struct bt *temp) //pass root node address as an
argument to a in-order function
{
if(temp != NULL)
{
in-order(temp->left); // Traverse the left sub-tree of root R
printf("%d\t", temp->data); //Visit the root, R and display.
in-order(temp->right); //Traverse the right sub-tree of root
R
}
}
//preorder traversing of a simple binary tree
void preorder(struct bt *temp) //pass root node address as an
argument to a preorder
//
function
{
if(temp != NULL)
{
printf("%d\t", temp->data); //Visit the root, R and display.
preorder(temp->left); // Traverse the left sub-tree of root R
preorder(temp->right); //Traverse the right sub-tree of root R
}
}
//post-order traversing of a simple binary tree
void postorder(struct bt *temp) //pass root node address as an
argument to post-order
//function
{
if(temp!=NULL)
{
postorder(temp->left); // Traverse the left sub-tree of root
R
postorder(temp->right); //Traverse the right sub-tree of root
R
printf("%d\t",temp->data); //Visit the root, R and display.
}
}
180 Data Structures using C
Output:
Nonlinear Data Structures: Trees 181
1. Traverse the left sub-tree of root R, that is, call in-order (left sub-tree).
2. Visit the root, R and process.
3. Traverse the right sub-tree of root R, that is, call in-order (right
sub-tree).
1. Traverse the left sub-tree of root R, that is, call postorder (left sub-tree)
2. Traverse the right sub-tree of root R, that is, call postorder (right
sub-tree)
3. Visit the root, R and process.
FIGURE 5.18
Reconstruction of a binary tree step 1.
FIGURE 5.19
Reconstruction of a binary tree step 2.
The frst value in the preorder traversal is the root of the binary tree because in
preorder traversing, the frst root is traversed, then the left sub-tree and then the
right sub-tree is traversed. Therefore, the node with data 11 becomes the root of
the binary tree. In in-order traversal, initially, the left sub-tree is traversed, then
the root node and then the right sub-tree. Therefore, the data before 11 in the in-
order list, that is, 14, 7, 21, 8 and 15 forms the left sub-tree, and the data after 11 in
the in-order list, that is, 61, 99 and 33 forms the right sub-tree. Figure 5.18 shows
the structure of the tree after dividing the tree into left and right sub-trees.
In the next iteration, 21 is the root for the left sub-tree. Hence, the data
before 21 in the in-order list, that is, 14, 7 form the left sub-tree of the node
that contains a value 21. The data that come to the right of 21 in the in-order
list that is 8, 15 forms the right sub-tree of the node with value 21. Figure 5.19
shows the structure of the tree after expanding the left and right sub-tree of
the node that contains a value 21.
Now the next data in the preorder list is 14 so now it becomes the root node.
The data before 14 in the in-order list forms the left sub-tree of the node that
contains a value 14. However, as there is no data present before 14 in in-order
list, the left sub-tree of the node with value 14 is empty. The data that come to
the right of 14 in the in-order list is 7 forms the right sub-tree of the node that
contains a value 14. Figure 5.20 shows the structure of the tree after expand-
ing the left and right sub-tree of the node that contains a value 14.
In the same way, one by one all the data are picked from the preorder list
and are treated as root and then from in-order list fnd elements in the right
and left sub-tree, and the whole tree is constructed in a recursive way or
non-recursive way, that is, iterative way (Figures 5.21 and 5.22).
Nonlinear Data Structures: Trees 183
FIGURE 5.20
Reconstruction of a binary tree step 3.
FIGURE 5.21
Reconstruction of a binary tree step 4.
FIGURE 5.22
Reconstruction of a binary tree step 5.
In-order traversal: 4 2 5 1 6 7 3 8
Post-order traversal: 4 5 2 6 7 8 3 1
184 Data Structures using C
FIGURE 5.23
Reconstruction of a binary tree step 1.
FIGURE 5.24
Reconstruction of a binary tree step 2.
The last value in the post-order traversal is the root of the binary tree because
in post-order traversing root is traversed in the last then the left sub-tree and
then the right sub-tree is traversed. Therefore, the node with data 1 becomes
the root of the binary tree. In in-order traversal, initially the left sub-tree is
traversed, then the root node and then the right sub-tree. Therefore, the data
before 1 in the in-order list that is 4, 2, 5 forms the left sub-tree and the data
after 1 in the in-order list that is 6, 7, 3, 8 forms the right sub-tree. Figure 5.23,
shows the structure of the tree after dividing the tree into the left and right
sub-trees.
In the next iteration 2 is root for the left sub-tree because it is the last ele-
ment in post-order traversing. Hence, the data before 2 in the in-order list
that is 4 forms the left sub-tree of the node that contains a value 2. The data
that comes to the right of 2 in the in-order list that is 5 forms the right sub-
tree of the node with value 2. Figure 5.24 shows the structure of the tree after
expanding the left and right sub-tree of the node that contains a value 2.
In the same way, one by one last data elements are picked from the
post-order list and are treated as root, and then from the in-order list fnd
elements in the right and left sub-tree and the whole tree is constructed in a
recursive way or non-recursive way (Figures 5.25 and 5.26).
FIGURE 5.25
Reconstruction of a binary tree step 3.
FIGURE 5.26
Reconstruction of a binary tree step 4.
trees post and preorder traversing the sequence may be the same as shown
in Figure 5.27.
Preorder traversal: 1 - 2 - 3
Post-order traversal: 3 - 2 - 1
In Figure 5.27a and b, both preorder and post-order traversal give us the same
result. That is, using preorder and post-order traversal, we cannot predict
exactly which binary tree we want to construct. That means ambiguity is there.
FIGURE 5.27
Binary tree.
186 Data Structures using C
However, if we know that the binary tree is strictly or a full binary tree, we
can construct the binary tree without ambiguity.
Take an example:
Preorder traversal: 1 2 4 5 3 7 8
Post-order traversal: 4 5 2 7 8 3 1
The last value in the post-order traversal is the root of the binary tree. The
frst value in preorder traversal is also root. Therefore, the node with data 1
becomes the root of the binary tree. The value next to 1 in preorder, must be
left child of the root. Therefore, we know 1 is root and 2 is the left child. Now
we know 2 is the root of all nodes in the left sub-tree. All nodes before 2 in
post-order must be in the left sub-tree that is 4, 5 and 2. Now we know 1 is
the root, elements 4, 5 and 2 are in the left sub-tree, and the elements 7, 8 and
3 are in the right sub-tree (Figures 5.28 and 5.29).
In the same way, one by one last data elements are picked from the post-order
list and are treated as root and then from in-order list fnd elements in the
right and left sub-tree, and the whole tree is constructed either in a recursive
way or in a non-recursive way, i.e., iterative way (Figure 5.30).
FIGURE 5.28
Reconstruction of a full binary tree step 1.
FIGURE 5.29
Reconstruction of a full binary tree step 2.
Nonlinear Data Structures: Trees 187
FIGURE 5.30
Reconstruction of a full binary tree step 3.
FIGURE 5.31
Binary search trees.
188 Data Structures using C
FIGURE 5.32
Before insertion of a node in the binary search tree.
Nonlinear Data Structures: Trees 189
FIGURE 5.33
After insertion of node 32 in a binary search tree.
FIGURE 5.34
Before deletion of a leaf node from binary search tree.
In the above BST, the node having value 33 is a leaf node, that node we
want to delete means that we will frst search the node 33 in the BST and
fnd its parent node that is 15. Then fnd 33 nodes are left or right side of the
15-parent node. In the above example, 33 nodes are on the right side of parent
node 15 so make 15 node’s right pointer as NULL. In addition, free the node
33 as is shown in Figure 5.35.
FIGURE 5.35
After deletion of node 33 from binary search tree.
FIGURE 5.36
Before deletion.
FIGURE 5.37
After deletion of node 33 from binary search tree.
Nonlinear Data Structures: Trees 191
FIGURE 5.38
Before deletion of a node having two children.
FIGURE 5.39
After deletion of node 15 from a binary search tree having two children.
192 Data Structures using C
#include<stdio.h>
#include<stdlib.h>
struct bst
{
struct bst *left;
int data;
struct bst *right;
};
//Function prototypes
void insert(struct bst * root , struct bst * new1);
void in-order(struct bst *);
struct bst * search(struct bst * root, int key, struct bst **
parent);
void delet(struct bst *, int key);
//main function definition
FIGURE 5.40
Binary search tree.
Nonlinear Data Structures: Trees 193
int main()
{
int choice, key;
char ch;
struct bst *root,*new1,*temp,*parent;
root=NULL;
parent=NULL;
printf("\n Binary Search Tree:");
do
{
printf("1.insert\t 2.display \t 3.search \t 4.delete \t 5.exit
\n ");
printf(" Enter your choice");
scanf("%d", &choice);
switch(choice)
{
case 1:
do
{
new1=(struct bst *)malloc(sizeof(struct bst));
printf(" Enter data");
scanf("%d",&new1->data);
new1->left=NULL;
new1->right=NULL;
if(root==NULL)
{
root=new1;
}
else
{
insert(root,new1);
}
printf("\n Do you want to insert another node[y/n]: ");
ch=getche();
}while(ch=='y'|| ch=='Y');
break;
case 2:
if(root==NULL)
printf("\n First create Binary Search Tree");
else
in-order(root);
break;
case 3:
if(root==NULL)
printf("\n First create Binary Search Tree");
else
{
printf("\n Enter data which you want to search");
scanf("%d", &key);
temp=search(root, key, &parent);
194 Data Structures using C
printf("\n%d", temp->data);
}
break;
case 4:
if(root==NULL)
printf("\n First create Binary Search Tree ");
else
{
printf("\n Enter data which you want to delete");
scanf("%d", &key);
delet(root, key);
}
break;
case 5:
exit(0);
default:
printf("\n Wrong choice");
}
printf("\n Do you want to continue binary search tree[y/n]");
fflush(stdin);
scanf("%c",&ch);
}while(ch=='y' || ch=='Y');
return 0;
}
//insert an element in a binary search tree
void insert(struct bst *root, struct bst *new1)
{
if(root->data<new1->data)
{
if(root->right==NULL)
{
root->right=new1;
}
else
{
insert(root->right, new1);
}
}
if(root->data>new1->data)
{
if(root->left==NULL)
{
root->left=new1;
}
else
{
insert(root->left, new1);
}
}
Nonlinear Data Structures: Trees 195
}
//search a node in a binary search tree and return address of
searched node and address of its //parent node
struct bst * search(struct bst *root, int key, struct bst
**parent)
{
struct bst *temp;
temp=root;
while(temp!=NULL)
{
if(temp->data==key)
{
printf("\n Node is found");
return temp;
}
else
{
*parent=temp; //update address of parent node in
calling function also
if(temp->data<key)
{
temp=temp->right;
}
else
{
temp=temp->left;
}
} // completion of outer else statement
} //completion of while loop
return ;
}
//deleting a node having two children
if( (temp->right!=NULL) && (temp->left!=NULL) )
{
parent=temp;
temp_succ=temp->right;
while(temp_succ->left!=NULL) //find in-order successor of
temp node
{
parent=temp_succ;
temp_succ=temp_succ->left;
}
temp->data=temp_succ->data; //copy data of in-order successor
node data into temp node
if(temp_succ==temp->right) //if in-order successor node is
right side of temp node
{
parent->right=NULL;
}
else //if in-order successor node is left side of temp
node
{
parent->left=NULL;
}
free(temp_succ); //free in-order successor node
temp_succ = NULL;
}
//deleting a node having only right child
else if((temp->right!=NULL)&&(temp->left==NULL))
{
if(parent->right==temp) //find whether temp node is left or
right side of parent node
{
parent->right=temp->right;
}
else
{
parent->left=temp->right;
}
temp->right=NULL;
temp->left=NULL;
free(temp);
temp=NULL;
}
Nonlinear Data Structures: Trees 197
Output:
struct bst
{
struct bst *left; //Store address of left sub-tree
int data; // Store the data in a node
struct bst *right; // Store address of right sub-tree
};
Step 3: Initialize the structure’s pointer type of variables such as root, parent,
new1 and temp as a NULL.
Step 4: Create a new node using dynamic memory management as
Here, malloc() function reserves the block of memory required for the new
node and that address is stored into the new1 pointer type of variable.
Step 5: Then insert new data into the data part of the newly created node
also make right and left pointer as NULL using,
Step 6: Check whether or not the root node has a NULL address. If the root
contains a NULL address, then assign the address of the new node to the
root.
Step 7: Otherwise, if the root node contains some address other than NULL,
then, call to insert function and pass root node’s address and newly created
node’s address as an argument.
Step 8: Ask the user to insert more nodes in the BST.
Step 9: If the user said yes, then repeat steps 4–8.
Step 10: If the user said no, then stop creating BST.
Step 11: Stop
Step 1: Start
Step 2: Check the data in the root node and in the new node. If the root
node’s data are less than the new node’s data, then go to the right sub-tree.
In addition, check whether or not the root node’s right pointer contains the
NULL address. If the root node’s right pointer contains the NULL address,
then attach a new node to the current root node’s right. Otherwise, call the
insert function recursively with the new root node’s address and address of
the newly created node. Here, the current root node contains the address of
200 Data Structures using C
the right sub-tree. Here, the address of newly created node’s address remains
the same, which is shown as follows:
Step 4: If the new node is placed in its correct position, then stop calling the
insert function recursively.
Step 5: Stop
Step 1: Start
Step 2: Check whether a BST is created or not.
If root=NULL, then
Nonlinear Data Structures: Trees 201
Repeat steps 4–7 till the temp pointer contains a NULL address.
Step 8: If the temp pointer contains the NULL address, then print “Node
is not found."
Step 9: Stop.
Step 1: Start
Step 2: Check whether or not a BST is created.
If root=NULL, then
Print “First create Binary Search Tree."
Otherwise
Take the key from the user whom you want to delete from the BST.
Step 3: Call to search function. After the execution of the search function
returns two addresses, one address of node that we want to delete in temp
pointer and another address of parent node which we want to delete into
parent pointer.
Step 4: First check whether or not the temp pointer is NULL. If the temp
pointer is NULL, then print the message “Node is not found in Binary search
tree” and return to the calling function.
Step 5: If the temp pointer is not NULL, then check whether a temp pointer
contains the address of the root node. If temp contains the address of root
202 Data Structures using C
node, then print message “Node which you want to delete is a root node and
we cannot delete root” and return to the calling function.
Step 6: If temp pointer does not contain addresses of the root node, then
check node that we want to delete having two children, if this condition is
true, then found its in-order successor and replace the deleted node value by
in-order successor node’s value and free the in-order successor node from
the BST.
if( (temp->right!=NULL) && (temp->left!=NULL) )
{
parent=temp;
temp_succ=temp->right;
while(temp_succ->left!=NULL) //find in-order successor
of temp node
{
parent=temp_succ;
temp_succ=temp_succ->left;
}
temp->data=temp_succ->data; //copy data of in-order
successor node data into temp
//node
if(temp_succ==temp->right) //if in-order successor
node is right side of temp node
{
parent->right=NULL;
}
else //if in-order successor node is left side of
temp node
{
parent->left=NULL;
}
free(temp_succ); //free in-order successor node
temp_succ = NULL;
}
Step 7: If the node that we want to delete does not contain two children,
then check whether the node contains the right child only. If this condition
is true, then fnd whether the temp node is the left or right side of the par-
ent node. If the temp node is the right side of the parent node, then assign
the address of the temp node’s right pointer address to the parent node’s
right pointer address. Otherwise, assign the address of the temp node’s right
pointer address to the parent node’s left pointer address. In addition, free the
temp node.
else if((temp->right!=NULL)&&(temp->left==NULL))
{
if(parent->right==temp) //find whether temp node is
left or right side of parent node
{
parent->right=temp->right;
}
Nonlinear Data Structures: Trees 203
else
{
parent->left=temp->right;
}
temp->right=NULL;
temp->left=NULL;
free(temp);
temp=NULL;
}
Step 8: If the node that we want to delete does not contain only the right
child, then check whether the node contains the left child only. If this condi-
tion is true, then fnd whether the temp node is the left or right side of the
parent node. If the temp node is the right side of the parent node, then assign
the address of the temp node’s left pointer address to the parent node’s right
pointer address. Otherwise, assign the address of the temp node’s left pointer
address to the parent node’s left pointer address. In addition, free the temp
node.
else if((temp->right==NULL)&&(temp->left!=NULL))
{
if(parent->left==temp) //find whether temp node is left
or right side of parent node
{
parent->left=temp->left;
}
else
{
parent->right=temp->left;
}
temp->right=NULL;
temp->left=NULL;
free(temp);
temp=NULL;
}
Step 9: If the node that we want to delete does not contain only the left child,
then check whether the node does not contain both left and right child. If this
condition is true, then fnd whether the temp node is the left or right side of the
parent node. If the temp node is the left side of the parent node, then the parent
node’s left pointer is assigned address as NULL, otherwise the parent node’s
right pointer is assigned address as NULL. In addition, free the temp node.
else if((temp->right==NULL)&&(temp->left==NULL))
{
if(parent->left==temp) //find whether temp node is left
or right side of parent node
{
parent->left=NULL;
}
else
{
204 Data Structures using C
parent->right=NULL;
}
free(temp);
temp=NULL;
}
Step 10: After checking all conditions, the print value of the deleted
node.
Step 11: Stop
//display binary search tree in in-order traversing
method
void in-order(struct bst *temp)
{
if(temp!=NULL)
{
in-order(temp->left);
printf("\n%d",temp->data);
in-order(temp->right);
}
}
1. Traverse the left sub-tree of root R, that is, call in-order (left sub-tree)
2. Visit the root, R and process.
3. Traverse the right sub-tree of root R, that is, call in-order (right sub-tree)
FIGURE 5.41
Huffman tree.
Each node of a binary tree, that is, in a binary expression tree, has zero, one,
or two children. This constricted arrangement simplifes the processing of
expression trees.
5.8 Heaps
5.8.1 Basic of Heap data Structure
The heap data structure is a special type of binary tree.
Binary heap is of two types:
Nonlinear Data Structures: Trees 207
1. Max heap
2. Min heap
1. The binary tree is an almost complete binary tree. That is, each leaf
node in the tree is either at level d or at level d-1, which means that
only one difference between levels of leaf nodes is permitted. At
depth d, that is the last level, if a node is present, then all the nodes to
the left of that node should also be present first and no gap between
the two nodes from left to the right side of level d.
2. Keys in nodes are arranged such that the content or value of each
node is less than or equal to the content of its father or parent node,
which means for each node info[i] <= info[j], where j is the father of
node i. This heap is called as max heap.
Here, in heap, each level of binary tree is filled from left to right, and a new
node is not placed on a new level until the preceding level is full.
In a min binary heap, the key at the root must be minimum among all keys
present in Binary Heap. The same characteristic must be iteratively true for
all nodes in a binary tree.
Examples of Max Heap (Figure 5.42).
FIGURE 5.42
Examples of max heap and not max heap.
208 Data Structures using C
2. Deletion
3. Finding a maximum value.
FIGURE 5.43
Max heap of size 5.
Nonlinear Data Structures: Trees 209
Step 2: Compare the new node value (65) with its parent node value (35).
That means 65 > 35
Here the new node value (65) is greater than its parent value (35), then swap
both of them. After sapping, max heap is as shown in below fgure:
Step 3: Now, again compare a new node value (65) with its parent node
value (55). Here the new node value (65) is greater than its parent value (55),
then swap both of them. After sapping, max heap is as shown in below fgure:
Step 4: Now new node is a root node hence stopping comparing and the
fnal heap of size 6 is as shown in the Figure 5.44.
210 Data Structures using C
FIGURE 5.44
Max heap of size 6 after insertion of node 65.
FIGURE 5.45
Max heap of size 6.
Nonlinear Data Structures: Trees 211
In the above max heap, if we want to delete 65 root nodes, then follow the
following steps:
Step 1: Swap the root node 65 with the last node 35 in max heap. After
swapping, the max heap is as follows:
Step 2: Delete the last node that is 65 from max heap. After deleting node
with value 65 from max heap, the max heap is as follows:
Step 3: Compare root node 35 with its left child 32. Here, the node with
value 35 is larger than its left child. Therefore, we compare node with value
35 is compared with its right child 55. Here, the node with value 35 is smaller
than its right child 55. Therefore, we swap both of them. After swapping,
max heap is as follows:
212 Data Structures using C
Here, the node with value 35 does not have left and right child. Therefore,
we stop the process.
Finally, max heap after deleting root node 65 is as follows:
1. Heap Sort: Heap sort uses a binary heap for sorting an array in O (n
log n) time.
2. Graph Algorithms: The priority queues are particularly used in
graph algorithms like Dijkstra’s shortest path and Prim’s minimum
spanning tree.
3. Priority Queue: Priority queues may be implemented effectively
using binary heap.
4. Many problems can be resolved effectively by utilizing heaps such as:
i. Nth largest element in an array.
ii. Sort an almost sorted array.
iii. Merge N number of sorted arrays.
node in the tree is either −1, 0 or +1. In other words, a binary tree is said to
be balanced if for every node’s height of its children differs by at most one.
In an AVL tree, every node maintains extra information known as balance
factor. The AVL tree was initiated in the year 1962 by G.M. Ade’son-Ve’skii
and E.M. Landis in their honor’s height balanced BST is termed as AVL tree.
In the complete balanced tree, left and right sub-trees of any node would
have the same height. Every AVL Tree is a BST, but all the BSTs need not to
be AVL trees.
5.9.2 Definition
An empty tree is height-balanced, if T is a non-empty BST with TL and TR as
its left and right sub-tree, then T is height-balanced if,
1. L L rotation
2. R R rotation
3. L R rotation
4. R L rotation
Example:
1. L L rotation:
It is used when a new node is inserted in the left sub-tree of the left
sub-tree of node A.
LL Rotation
Balanced Unbalanced Rebalanced sub-tree
Sub-tree due to insertion of node 5
2. R R rotation:
It is used when a new node is inserted in the right sub-tree of the
right sub-tree of node A.
RR Rotation
Balanced Unbalanced Rebalanced sub-tree
Sub-tree due to insertion of node 41
3. L R rotation:
It is used when a new node is inserted in the right sub-tree of the
left sub-tree of node A.
LR Rotation
4. R L rotation:
It is used when a new node is inserted in the left sub-tree of the
right sub-tree of node A.
RL Rotation
Balanced Unbalanced Rebalanced sub-tree
Sub-tree due to insertion of node 45
Step 1: Start
Step 2: Read the search element from the user.
Step 3: Next, compare the search element to the root node value in the
tree.
Step 4: If both are equal, then display “Element is Searched” and wind
up the search function.
Step 5: If both are not equal, then verify whether a search element is
smaller or greater than that of the parent node value.
Step 6: If the search element is smaller, then continue the search process
in the left sub-tree.
Step 7: If the search element is larger, then continue the search process
in the right sub-tree.
Step 8: Repeat the same as long as we fnd the exact element or we fnish
with a leaf node.
Step 9: If we reach the node with a search value, then display “Element
is Searched” and terminate the function.
216 Data Structures using C
Step 10: If we reach a leaf node and it is also not matching, then display
“Element is not Searched” and terminate the function.
Step 11: Stop.
Step 1: Start
Step 2: Insert the new item in the tree with the BST insertion logic.
Step 3: Once inserted, check the balance factor for each node.
Step 4: If the balance factor of every node is 0 or 1 or −1, then go to step 6.
Step 5: If the balance factor of a node is not 0 or 1 or −1, then the tree is
said to be unbalanced. Then perform the appropriate rotation tech-
nique to achieve balance. In addition, get on with the next operation.
Step 6: Stop.
Example:
Insertion of the following nodes in an AVL tree:
55, 66, 77, 15, 11 and 33
66 No rebalancing
needed
77
RR rota˜on
(Continued)
Nonlinear Data Structures: Trees 217
11
LL rotation
33
LR rotation
5.9.5 Advantages
1. When compared to the number of insertion and deletions, the num-
ber of times a search operation is carried out is relatively large. The
use of an AVL tree always results in superior performance.
2. The main objective here is to keep the tree balanced at all times. Such
balancing causes the depth of the tree to remain at its minimum,
reducing the overall cost of search.
3. AVL tree gives the best performance for dynamic tables.
218 Data Structures using C
5.9.6 Disadvantages
5.10 B Trees
5.10.1 Introduction of B Tree
B tree is not a binary tree. B tree is a balanced m-way tree that is each tree
node contains a maximum of (m-1) data elements in the node and has m
branches or links.
For example, a balanced four-way tree node contains three data felds and
four-link felds shown as follows:
3 data fields
21 31 41
4 link fields
5. When a new key is to be inserted into a full node, the node is split
into two nodes and key with a median value is inserted into the par-
ent node. If the parent node is root and it is likewise full, then a new
root is created.
For example, B-Tree of Order 4 contains maximum three key values in a node
and maximum four children for a node.
Step 1: Start
Step 2: First verify if the tree is empty.
Step 3: If the tree is empty, create a new node with a new key value and
place it in the tree as the root node.
Step 4: If the tree is not empty, then discover a leaf node to which the
new key value can be inserted using the BST logic.
Step 5: If that leaf node has an empty place, then add the new key value
for that leaf node by preserving ascending order of the key value as
part of the node.
Step 6: If that leaf node is already full, then split that leaf node by send-
ing a middle value to its parent node. Repeat the same until sending
value is fxed into a node.
Step 7: If the splitting has taken place of the root node, then the middle
value becomes a new root node in the tree, and the height of the tree
is increased by one.
Step 8: Stop.
Example:
Consider a building of B-tree of order or degree 4 that is a balanced four-
way tree where each node can hold three data values and have four links or
branches.
Suppose we want to insert the following data values in B-tree,
1, 5, 6, 2, 8, 11, 13, 18, 20, 7, 9.
220 Data Structures using C
Steps:
First, value 1 is placed in a node, which can also accommodate next two
values, that is, 5 and 6.
5.10.3.2 B-Tree Deletion
The delete method lets you search for the first record you want to delete.
Example:
If 20 is searched, then delete 20 from that node. After the deletion, B-tree is
like as follows:
If element 5 is deleted, then find its successor node element that is 6 and
replace 5 with 6.
After deletion of element 5, B-tree becomes as follows:
222 Data Structures using C
Step 1: Start.
Step 2: First, read the search element from the end user.
Step 3: Then compare, the search element with the frst key value of the
root node in the tree.
Step 4: If both are equal, then display “Given node is searched” and
wind up the function.
Step 5: If both are not matching, then verify whether a search element is
smaller or larger than that key value.
Step 6: If the search element is smaller, then continue the search process
in the left sub-tree.
Step 7: If the search element is larger, then compare with the next key
value in the same node and repeat steps 3, 4, 5 and 6 until we found
an exact match or comparison completed with the last key value in
a leaf node.
Step 8: If we completed with last key value in a leaf node, then display
“Element is not found” and terminate the function.
Step 9: Stop.
5.11 B+ Trees
5.11.1 Introduction of B+ Tree
B+ tree is not a binary tree. B+ tree is a balanced m-way tree, that is, each tree
node contains a maximum of (m-1) data elements in the node and have m
branches or links.
In B+ tree, all leaves have been joined to form a linked list of keys in a
sequential order.
Nonlinear Data Structures: Trees 223
The linked leaves are a brilliant aspect of B+ tree. Keys can be accessed effec-
tively both directly and sequentially. B+ tree is used to offer indexed sequen-
tial fle organization. The key values in the sequence set are the key values in
the record collection. The key values in the index part exist solely for internal
purposes of direct access to the sequence set.
In the B+ tree, + indicates extra functionality than that of the B-tree, that is,
leaf nodes are connected.
For example, the B+ Tree of order 3 contains maximum two key values in a
node and maximum three children or link part of a node.
Step 1: Start.
Step 2: First verify if the tree is empty.
Step 3: If the tree is empty, create a new node with a new key value and
place it in the tree as the root node.
Step 4: If the tree is not empty, then discover a leaf node to which the
new key value can be added using BST logic.
Step 5: If that leaf node has an empty position, then add the new key
value for that leaf node by preserving ascending order of key value
within the node.
Step 6: If that leaf node is already full, then split that leaf node by send-
ing the median value to its parent node. Repeat the same until send-
ing value is fxed into a node.
Step 7: If the splitting is occurring to the root node, then the median
value becomes a new root node in the tree and the height of the tree
is increased by one.
Step 8: After inserting a new key value into B+ tree, all leaves have been
connected to form a linked list of keys in sequential order.
Step 9: Stop.
Example:
Consider a building of the B+ tree of order or degree 3 that is a balanced
three-way tree where each node can hold two data values and have three
links or branches.
Suppose we want to insert the following data values in the B+-tree,
10, 20, 30, 12, 21, 55 and 45.
Here, the B+ tree of order 3 having two data part. Therefore, we frst insert
10 in a node then 20 data at the next right empty feld in node, then B+ tree
looks like as follows:
After the insertion of values 30 in the B+ tree node, split, then node having
median 20 and make that node as a parent node and insert 20 and 30 value
into one node and 10 values in another node and now these two nodes
become leaf nodes, so connect that two nodes using a linked list. After insert-
ing value 30, B+ tree looks like as follows:
Nonlinear Data Structures: Trees 225
1. If the deleted key is the indexed node’s value, then delete the index
node’s key and data from the leaf node.
2. If the leaf node underfows, merge with siblings and delete key in
between them.
226 Data Structures using C
3. If the index node underfows, merge with siblings and move down
key in between them.
Deletion of 30 values from above B+ tree, then 30 values are in both leaf node
and index node. Therefore, delete the value from both leaf and index node.
Then index node goes underfow condition, so the successor key value 55
becomes median and goes to its parent node. Therefore, 45 and 55 values are
now present in the parent node, that is, the index node.
Step 1: Start.
Step 2: First, read the search element from the end user.
Step 3: Then compare the search element with a frst key value of the
root node in the tree.
Step 4: If both are equal, then display “Given node is found” and termi-
nate the function.
Nonlinear Data Structures: Trees 227
Step 5: If both are not matching, then check whether a search element is
smaller or larger than that key value.
Step 6: If the search element is smaller, then continue the search process
in the left sub-tree.
Step 7: If the search element is larger, then compare with the next key
value in the same node and repeat steps 3, 4, 5 and 6 until we fnd
an exact match or comparison completed with a last key value in a
leaf node.
Step 8: If we accomplished with last key value in a leaf node, then dis-
play “Element is not found” and wind up the function.
Step 9: Stop.
5. If a node has two children that node we want to delete from a BST,
then that deleted node must be replaced by its
A. In-order successor
B. In-order predecessor
C. Post-order successor
D. Post-order predecessor
Answer: A
6. A BST is formed from the given sequence 6, 9, 1, 2, 7, 14, 12, 3, 8 and 18.
The minimum number of nodes required to be added into this tree
to form an extended binary tree is?
A. 3
B. 6
C. 8
D. 11
Answer: D
7. In a full binary tree, every internal node has exactly two children. A
full binary tree with 2n+1 nodes contains,
A. 2n leaf nodes
B. n+1 internal nodes
C. n+1 exterior nodes
D. n-1 internal nodes
Answer: C
A. Binary tree
B. Binary search tree
C. Max-heap
D. Min-heap
Answer: D
10. In which of the following tree, parent node has a key value greater
than or equal to the key value of both of its children?
A. Binary search tree
B. Threaded binary tree
C. Complete binary tree
D. Max-heap
Answer: D
11. A complete binary tree T has n leaf nodes. The number of nodes of
degree 2 in T is
A. log2n
B. n-1
C. n
D. 2n
Answer: B
13. The number of edges or links from the root node to the deepest leaf
is called _________ of the tree.
A. Height
B. Depth
C. Length
D. Width
Answer: A
16. Which type of binary tree produces the value in ascending sorted
order when it is traversed?
A. Binary search tree
B. Complete binary tree
C. Strictly binary tree
D. Almost complete binary tree
Answer: A
G = (V, E)
FIGURE 6.1
Directed graph.
As shown in Figure 6.1., the edges between vertices are ordered. In this
type of graph, edge E1 is in between vertices v1 and v2. The v1 is called head
and v2 is called tail. We can say, E1 is set of (V1, V2) and not of (V2, V1).
Similarly, in an undirected graph, edges are not ordered (Figure 6.2).
In this type of graph, that is an undirected graph, the edge E1 is set of
(V1, V2) or (V2, V1).
Consider the following directed graph (Figure 6.3):
V(G) = {A, B, C, D}
E(G) = {(A,A),(B,A),(B,D),(D,C),(A,B),(B,C),(A,C)}
In Figure 6.3, edge (A, B) and edge (B, A) are two different edges through
both the edges that connect vertex A and vertex B. Some edges may connect
FIGURE 6.2
An undirected graph.
FIGURE 6.3
Directed graph.
Nonlinear Data Structures: Graph 237
one node with itself. These edges are called loops. For example, edge (A, A)
is a loop.
The degree of a vertex is the number of edges incident to it. In-degree of a
vertex is the number of edges pointing to that vertex and out-degree of a vertex
is the number of edges pointing from that vertex. For example, the out-degree
of node B in Figure 6.3 is 3, and its in-degree is 1 and degree of node B is 4.
Note: A tree is a special case of a directed graph.
A graph need not be a tree, but a tree must be a graph. In a graph, a node
that is not adjacent to any other node is called an isolated node (Figure 6.4).
For example, node D in a graph is an isolated node shown in Figure 6.4. The
degree of an isolated node is zero.
A graph with undirected and directed edges is said to be a mixed graph as
shown in Figure 6.5.
FIGURE 6.4
Graph containing isolated node D.
FIGURE 6.5
Mixed graph.
FIGURE 6.6
Null graph.
238 Data Structures using C
FIGURE 6.7
Complete graph.
FIGURE 6.8
Strongly connected graph.
Nonlinear Data Structures: Graph 239
FIGURE 6.9
Unilaterally connected, strongly connected, and weakly connected digraph. (a) Strongly con-
nected graph. (b) Weakly connected graph but not unilaterally connected. (c) Unilaterally con-
nected but not strongly connected.
6.1.3.7 Multigraph
A graph G is called a multigraph if a graph contains loop or parallel edges.
The graph shown in Figure 6.11 is a multigraph.
FIGURE 6.10
Simple graph.
240 Data Structures using C
FIGURE 6.11
Multigraph.
FIGURE 6.12
Cyclic graph.
FIGURE 6.13
Acyclic graph.
Nonlinear Data Structures: Graph 241
FIGURE 6.14
Bipartite graph.
FIGURE 6.15
Complete bipartite graph.
In general, a bipartite graph has two sets of vertices, let us say, V1 and V2,
and if an edge is drawn, it should connect any vertex in set V1 to any vertex
in set V2. The graph shown in Figure 6.14 is bipartite.
FIGURE 6.16
Directed graph, G.
FIGURE 6.17
Adjacency matrix of directed graph G.
Nonlinear Data Structures: Graph 243
FIGURE 6.18
Undirected graph, G.
FIGURE 6.19
Adjacency matrix of undirected graph G.
1. Declare an array of M [size] [size] which will store the graph, where the
size = number of maximum nodes which we have stored in the graph.
2. Enter how many nodes you want in a graph.
3. Enter edges of graph by two vertices each say Vi, Vj indicates some edge.
4. If the graph is directed set M [i] [j] = 1. If the graph is undirected set
M [i] [j] = 1 and M [j] [i] = 1 as well.
5. When all edges in the desired graph are entered, print the graph
M [i] [j].
and de-allocations from an available pool. We will represent the graph using
adjacency lists. This adjacency list stores information about only those edges
that exist. The adjacency list contains a directory and a set of linked lists.
This representation is also known as node directory representation. The
directory contains one entry for each node of the graph. Each entry in the
directory points to a linked list that represents a node that is connected to
that node. Directory represent nodes and the linked list represent the edges.
Each node of the linked list has three felds:
1. Node identifer,
2. Link to next feld,
3. An optional weight feld contains the weight of the edge.
FIGURE 6.20
A directed graph.
Nonlinear Data Structures: Graph 245
FIGURE 6.21
Sample node.
FIGURE 6.22
Node directory representation for directed graph.
FIGURE 6.23
Weighted graph.
FIGURE 6.24
Sample node.
FIGURE 6.25
Node directory representation for a weighted graph.
FIGURE 6.26
Given graph G.
Solution:
Step 1:
Start from BFS (1),
Print value 1,
Delete node 1 from the queue and insert not visited adjacent nodes to
the queue.
Nonlinear Data Structures: Graph 249
Step 2:
Print value 2,
Delete node 2 from the queue and insert not visited adjacent nodes of 2
into the queue.
Step 3:
Adjacent nodes of 2 are {1, 5, 3, 6} but 1 and 3 are already visited so dis-
card it and add 5 and 6 nodes into the queue.
Print value 3,
Delete node 3 and insert non-visited adjacent node to the queue, then
250 Data Structures using C
Step 4:
Adjacent nodes of node 3 are {1, 2, 6}, but all are already visited so dis-
card it, and no node is added into the queue.
Print value 4,
Delete node 4 and insert non-visited adjacent nodes to the queue, then
Step 5:
Adjacent nodes of node 4 are {1, 7, 8}, but 1 is already visited so discard
it and insert 7 and 8 to the queue.
Print value 5,
Delete node 5 and insert non-visited adjacent nodes to the queue, then
Nonlinear Data Structures: Graph 251
Step 6:
Adjacent nodes of node 5 are {6, 2} already visited.
Print value 6,
Delete node 6 and insert non-visited adjacent nodes to the queue, then
Step 7:
Adjacent nodes of node 6 are {5, 2, 3} already visited.
Print value 7,
Delete node 7 and insert non-visited adjacent node to the queue, then
252 Data Structures using C
Step 8:
Print value 8,
Delete node 8 and insert non-visited adjacent nodes to the queue, then
Step 9:
Adjacent nodes of node 8 are {7, 4} already visited.
Queue is now empty because front > rear or front index cross to the rear
index, this condition shows that queue is empty, then stop the BFS
algorithm.
Nonlinear Data Structures: Graph 253
FIGURE 6.27
BFS spanning tree of Figure 6.25.
By using this trace, we will fnd the BFS spanning tree, which is as
follows:
Before that, spanning tree is a subset of Graph G, which has all the
nodes or vertices covered with the minimum possible number of
edges. Hence, a spanning tree does not have cycles or loops, and it
cannot be disconnected (Figure 6.27).
1 – 2 – 3 – 4 – 5 – 6 – 7 – 8.
void BF_Traversal()
{
int v;
for(v=0; v<n; v++)
state[v] = initial;
printf("Enter start Vertex for BFS: \n");
scanf("%d", &v);
BFS(v);
}
// pass node v as the first node for traversing graph using
BFS traversing technique
void BFS (int v)
{
int i;
insert_queue(v);
state[v] = waiting;
//Continue the while loop till queue is not empty
while( !isEmpty_queue() )
{
v = delete_queue( );
printf("%d ",v);
state[v] = visited;
//check all adjacent nodes of node v and check whether the
adjacent nodes are visited or not
for(i=0; i<n; i++)
{
if(adj[v][i] == 1 && state[i] == initial)
{
insert_queue(i);
state[i] = waiting;
} //if completed
} // for loop completed
} // while loop completed
printf("\n");
}
Nonlinear Data Structures: Graph 255
Output:
Step 1: Start with vertex 0, print it so ‘0’ node is printed. Mark 0 node as
visited.
Visited array
Step 2: Find adjacent vertex to 0, there are two adjacent vertices 1 and 2, out
of that choose one say node 1 is chosen if it is not visited, call DFS (1), that
is, 1 will get inserted into the stack, mark node 1 as visited in the visited
array.
FIGURE 6.28
An undirected graph.
Nonlinear Data Structures: Graph 259
Output:
Nonlinear Data Structures: Graph 261
1. Visited array
2. Cost matrix
3. Distance matrix
1. Start.
2. Create a cost matrix C [ ] [ ] from the adjacency matrix adj[ ] [ ].
C [i] [j] is a cost of going from vertex i to vertex j.
If there is no edge between vertices i and j, then C [i] [j] is set to be
infnity.
3. Array visited [ ] is initialized to zero.
for (i=0; i<n; i++)
visited [i]=0;
7. Stop.
Nonlinear Data Structures: Graph 263
Solution:
Source vertex is taken as 0.
Cost matrix:
Distance matrix:
FIGURE 6.29
Given undirected weighted graph G.
264 Data Structures using C
Visited array:
First iteration:
1. Select vertex 0.
2. Mark visited [0] as 1.
3. Calculate distance of vertex 1 from 0 using cost matrix. Cost of vertex
1 from 0 is 10.
4. Cost of vertices 3 and 4 from vertex 0 is 30 and 100, respectively.
Therefore, update the distance matrix.
Distance matrix:
Visited array
Second iteration:
1. Select vertex 1.
2. Mark visited [1] as 1.
3. Re-adjust distances.
4. Cost of going to vertex 2 from the source vertex 0, through selected
vertex 1 is given by, distance [1] + cost [1] [2] = 10 +50 = 60.
Distance of 60 is better than existing distance of ∞ or infnity.
5. Cost of going to vertex 3 from the source vertex 0, through selected
vertex 1 is given by, distance [1] + cost [1] [3] = 10 + ∞ = ∞
which is worse than existing distance of 30.
6. Similarly, cost of going to vertex 4 through vertex 1 is ∞ which is
worse than existing distance of 100.
Distance matrix:
Visited array:
Nonlinear Data Structures: Graph 265
Third iteration:
Vertex selected = 3
Cost of going to vertex 2 through 3 = dist[3] + cost[3] [2] = 30+20 = 50
Cost of going to vertex 4 through 3 = dist[3] + cost[3] [4] = 30+60 = 90
Distance of vertices 2 and 4 should be changed.
Distance matrix:
Visited array:
Fourth iteration:
Vertex selected = 2
Cost of going to vertex 4 through 2 = dist[2] + cost[2] [4] = 50+10 = 60
Distance of vertex 4 should be changed.
Visited array:
Simply, a spanning tree is a subset of an undirected Graph that has all the
vertices connected by a minimum number of edges.
If all the vertices are connected in a graph, then there exists at least one span-
ning tree. In a graph, there may exist more than one spanning tree. If graph G,
contains ‘n’ vertices, then the spanning tree contains ‘n’ vertices and (n-1) edges.
266 Data Structures using C
FIGURE 6.30
Undirected graph G.
(i) (ii)
(iii) (iv)
FIGURE 6.31
Given undirected graph G and its four spanning trees.
Nonlinear Data Structures: Graph 267
1. Prime’s algorithm
2. Kruskal’s algorithm
Prime’s Algorithm
1. Label all the vertices as unchosen.
2. Let the tree T consist of ‘n’ nodes, initially with no edge. T is also
called a solution vector.
3. Choose any arbitrary vertex ‘u’ and label it as chosen.
4. while (there is an unchosen vertex)
{
pick the lightest edge between any chosen ‘u’ and unchosen ‘v’
label v as chosen T = T + <u, v>
if and only <u, v> does not give rise to cycle in T
}
FIGURE 6.32
Given undirected weighted graph G.
5. Make the sum of all selected edge weights that gives us the mini-
mum weighted spanning tree.
6. Stop.
Solution:
1 2 3 4 5 6 7
° ˜ 1 ˜ 4 ˜ ˜ ˜ ˙
˝ ˇ
˝ 1 ˜ 2 6 4 ˜ ˜ ˇ
˝ ˜ 2 ˜ ˜ 5 6 ˜ ˇ
Adjacency Matrix : ˝ 4 6 ˜ ˜ 3 ˜ 4 ˇ
˝ ˇ
˝ ˜ 4 5 3 ˜ 8 7 ˇ
˝ ˜ ˜ 6 ˜ 8 ˜ 3 ˇ
˝ ˜ ˜ ˜ 4 7 3 ˜ ˇ
˛ ˆ
Step 1:
Set V = {1, 2, 3, 4, 5, 6, 7}
Set V’ = empty set initially
T = { } = empty set initially
1 Select Node 1:
a. 1 – 2 → 1
b. 1 – 4 → 4
270 Data Structures using C
FIGURE 6.33
Minimum cost-spanning tree for graph G.
2 Select Node 2:
a. 2 – 1 → 1
b. 2 – 3 → 2
c. 2 – 4 → 6
d. 2 – 5 → 4
3. Select Node 3:
a. 3 – 2 → 2
b. 3 – 5 → 5
c. 3 – 6 → 6
4. Select Node 4:
a. 4 – 1 → 4
b. 4 – 2 → 6
c. 4 – 5 → 3
d. 4 – 7 → 4
5. Select Node 5:
a. 5 – 2 → 4
b. 5 – 3 → 5
c. 5 – 4 → 3
d. 5 – 6 → 8
e. 5 – 7 → 7
Nonlinear Data Structures: Graph 271
6. Select Node 7:
a. 7 – 4 → 4
b. 7 – 5 → 7
c. 7 – 6 → 3
7. Select Node 6:
a. 6 – 3 → 6
b. 6 – 5 → 8
c. 6 – 7 → 3
Minimum weight = 1+2+4+3+4+3 = 17
Another minimum cost-spanning tree for graph G can be as follows
(Figure 6.34):
Minimum weight = 1+2+3+4+4+3 = 17
FIGURE 6.34
Minimum cost-spanning tree for graph G.
272 Data Structures using C
replace W1 and W2 in Vs by W1 U W2
add <V, W> to T
}
Example: Find out the minimum cost of a spanning tree by using Kruskal’s
algorithm (Figure 6.35).
Nonlinear Data Structures: Graph 273
FIGURE 6.35
Given undirected weighted graph G.
Solution:
Step 1:
T = null
Vs = null
E = {<V1, V2>, <V2, V3>….} //set of all edges
T is a solution vector, initially null with no edges.
Vs is the set of vertices and at the initial step it is null.
Step 2: Arrange all the edges in ascending order according to their weights.
When you select any edge then add it to the set of vertices Vs and the Tree,
T is solution vector.
Care must be taken that there should not be any cycle.
Priority Queue:
V1 – V7 → 1
V3 – V4 → 3
V2 – V7 → 4
V3 – V7 → 9
V2 – V3 → 15 // creates loop so discard
V4 – V7 → 16 // creates loop so discard
V4 – V5 → 17
V1 – V2 → 20 // creates loop so discard
274 Data Structures using C
V1 – V6 → 23
V5 – V7 → 25
V6 – V7 → 36
V5 – V6 → 38
Vs = {{V1}, {V2}, {V3}, {V4}, {V5}, {V6}, {V7}}
Step 7:
The next edge is V2 – V3 with weight 15. We discard this edge because it
results in cycle. After all, V2 and V3 are in the same set in Vs.
Therefore, the next edge is V4 – V7 with weight 16, we discard this edge also
because it results in cycle. V4 and V7 are in the same set in Vs.
Therefore, the next edge is V4 – V5 with weight 17. Select it.
Vs = {{V1, V7, V2, V3, V4, V5}, {V6}}
T = {<V1, V7>, <V3, V4>, <V2, V7>, <V3, V7>, <V4, V5>}
Step 8:
The next edge is V1 – V2 with weight 20. We discard this edge because it
results in cycle. V1 and V2 are in the same set in Vs.
The next edge is V1 – V6 with weight 23. Select it.
Vs = {{V1, V7, V2, V3, V4, V5, V6}}
T = {<V1, V7>, <V3, V4>, <V2, V7>, <V3, V7>, <V4, V5>, <V1, V6>}
Step 9: So all vertices of the given graph are visited. Stop this process. We get
tree which is minimum cost-spanning tree as follows (Figure 6.36):
Minimum cost of spanning tree= 23 + 1 + 4 + 9 + 3 + 17 = 57
Nonlinear Data Structures: Graph 275
FIGURE 6.36
Minimum cost-spanning tree for graph G.
Note: The above tree satisfes all the conditions to become a spanning tree
and mainly it uses greedy strategy because we choose or select the edge with
minimum weight as the frst edge instead of choosing any random edge like
in Prime’s Algorithm.
Example: Find minimum cost-spanning tree by using Kruskal’s algorithm
(Figure 6.37).
FIGURE 6.37
Given undirected weighted graph G.
276 Data Structures using C
Solution:
Step 1:
T = null
Vs = null
E = {<V1, V2>, <V2, V3>….} //set of all edges
T is a solution vector, initially null with no edges.
Vs is the set of vertices and at the initial step it is null.
Step 2: Arrange all the edges in ascending order according to their weights.
When you select any edge, then add it to the set of vertices Vs and the Tree,
T is the solution vector.
Care must be taken that there should not be any cycle.
Priority Queue:
A–F→2
B–F→3
A – B → 4 // creates loop so discard
C–E→5
B–C→6
B – E → 7 // creates loop so discard
D–E→7
C–D→8
E–F→9
Vs = {{A}, {B}, {C}, {D}, {E}, {F}}
Step 5:
The next edge is A – B with weight 4. We discard this edge because it results
in cycle. A and B are in the same set in Vs.
Step 6:
Therefore, the next edge is C – E with weight 5. Select it.
T = {<A, F>, <B, F>, <C, E>}
VS = {{A, F, B}, {D}, {C, E}}
Nonlinear Data Structures: Graph 277
Step 7:
Therefore, the next edge is B – C with weight 6, select it.
T = {<A, F>, <B, F>, <C, E>, <B, C>}
VS = {{A, F, B, C, E}, {D}}
Step 8:
The next edge is B – E with weight 7. We discard this edge because it results
in cycle. In addition, B and E are in the same set in Vs.
Step 9:
Therefore, next edge is D – E with weight 7, select it.
T = {<A, F>, <B, F>, <C, E>, <B, C>, <D, E>}
VS = {{A, F, B, C, E, D}}
Step 10: So all vertices of a given graph are visited. Stop this process. We get
tree that is minimum cost-spanning tree as follows (Figure 6.38):
Minimum cost = 2+3+5+6+7 = 23
FIGURE 6.38
Minimum cost-spanning tree for graph G in Figure 6.36.
278 Data Structures using C
4. In the while loop, the loop repeats itself for the entire edge list. Hence,
the complexity would be O (E ).
5. Complexity of the algorithm would hence be O ( E log 2 E ).
10. For the undirected, weighted graph given below, which of the fol-
lowing sequences of edges represents a correct execution of Prim’s
algorithm to construct an MST?
A. (a, b), (d, f), (f, c), (g, i), (d, a), (g, h), (c, e), (f, h)
B. (c, e), (c, f), (f, d), (d, a), (a, b), (g, h), (h, f), (g, i)
C. (d, f), (f, c), (d, a), (a, b), (c, e), (f, h), (g, h), (g, i)
D. (h, g), (g, i), (h, f), (f, c), (f, d), (d, a), (a, b), (c, e)
Answer: (C)
11. What is the number of edges present in a complete graph having n
vertices?
A. (n*(n+1))/2
B. (n*(n-1))/2
C. n
D. Information given is insuffcient
Answer: B
12. In the given graph, identify the cut vertices.
282 Data Structures using C
A. B and E
B. C and D
C. A and E
D. C and B
Answer: D
13. In a simple graph, the number of edges is equal to twice the sum of
the degrees of the vertices.
A. True
B. False
Answer: B
14. What is the maximum number of edges in a bipartite graph having
10 vertices?
A. 24
B. 21
C. 25
D. 16
Answer: C
15. If a simple graph G, contains n vertices and m edges, the number of
edges in the Graph G’(Complement of G) is ___________
A. (n*n-n-2*m)/2
B. (n*n+n+2*m)/2
C. (n*n-n-2*m)/2
D. (n*n-n+2*m)/2
Answer: A
16. A graph with all vertices having an equal degree is known as a
__________
A. Multigraph
B. Regular graph
C. Simple graph
D. Complete graph
Answer: B
17. Which of the following ways can be used to represent a graph?
A. Adjacency list and adjacency matrix
B. Incidence matrix
Nonlinear Data Structures: Graph 283
a. Internal search
The searching method in which all elements remain sustained in
main memory is called internal search.
The time required is less but is perfect for a small amount of data.
Linear search, binary search, binary search tree and AVL tree are
internal searching techniques.
b. External search:
The searching method in which elements are kept in secondary
storage is called external search. The time required is longer, and
the perfect search technique for a lot of data. B tree and B+ tree are
external searching techniques.
return 0;
}
Output:
1. Start.
2. The array must be in ascending or descending sorted order. Then
fnd the middle element of the array, which will be referred to as mid.
Searching and Sorting Techniques 289
FIGURE 7.1
Binary search.
3. Compare the middle element, mid with searched element or key ele-
ment, key.
4. There are three cases assumed that the array is in ascending order:
i. If mid = key, that is, if mid is the desired element, then the search
is successful.
ii. If mid > key, that is, the mid element is greater than key element,
then search only in the frst half of the array.
iii. If mid < key, that is, the mid element is less than key element, then
search only in the second half of the array, considered array ele-
ments are sorted in ascending order.
5. Repeat the above steps 1–3 until the key element is found.
6. Stop.
In this algorithm, every time we reduce the search area. Therefore, the num-
ber of comparisons keeps on decreasing. Even in the worst case, the number
of comparisons is at most log2 (N + 1) (Figure 7.1).
= (3+4)/2 = 3
290 Data Structures using C
mid
9 12 24 30 45 a
0 1 2 3 4
beg last
a[mid]<45
Then calculate the beg index as, beg = mid + 1 = 3 + 1 = 4 and last = 4.
Step 3: mid = (beg + last)/2
= (4+4)/2 = 4
mid
9 12 24 30 45 a
0 1 2 3 4
beg / last
flag=1;
}
if(item<a[mid])
end=mid-1;
else
beg=mid+1;
}
if(flag==0)
printf("\n Item is not found in the list.");
return 0;
}
Output:
TABLE 7.1
Analysis of Searching Techniques
Analysis of Searching
Techniques Linear Search Binary Search Hashing
Best case Ω (1) Ω (1) Ω (1)
Average case Θ(n) Θ(log2 n) Θ(1)
Worst case O(n) O(log2 n) O(1)
Hash Table
Passed to generates 0 Key element or data
Hash
Key element Hash key 1 Key element or data
Function
2 Key element or data
… Key element or data
n Key element or data
FIGURE 7.2
Basic concept of hashing and hash table.
FIGURE 7.3
Hashing.
Searching and Sorting Techniques 295
Key: 325
325 * 325 = 105625
Hash key: 56
Example:
Key: 3455677234
Partitioning: 345 |567 | 723 |4
Adding: 345 + 567 + 723 + 4 = 1639
i. Fold shift:
Key value: 123456789
123+456+789=1368, here 1 is carry and discard or remove the carry
digit from obtained address or hash key. Hence, 368 is new hash
key or address.
ii. Fold boundary:
Key: 123456789
321 (digit reversed) + 456 + 987 (digit reversed) = 1764, here 1 is carry
and discard or remove the carry digit from obtained address or
hash key. Hence, 764 is a new hash key or address.
7 0 0 1 0
8 0 1 0 0
Positions 2 and 3 are best distributed. Hence, we have addressed the hash key
as 23, 45 and 78.
Index data
0
1 131
2 21
3 31
4 44
5 515
6 61
7 77
FIGURE 7.4
Linear probing.
298 Data Structures using C
FIGURE 7.5
Chaining without replacement.
Example:
Suppose we have the following elements (Figure 7.5):
131, 21, 31, 4, 5, 61, 2, 22
Explanation:
Here in chaining without replacement method, frst 131 element’s hash key
is generated by using hash function 131% 10, that is, 1. Then 131 is placed
in the array index of 1. Then the next key element is 21, and its hash key is
generated which is also 1, then place that 21 key element after 131, means 21
is placed at index 2, but in the chain column place, the value of 2 so the key
element’s having the same hash key is chained together. Similarly, for key
element 31 having hash key 1, then place 31 at the index 3 and update the
chain value of 21 elements as 3 and so on for next key elements.
FIGURE 7.6
Chaining with replacement.
Searching and Sorting Techniques 299
1. Linear probing
2. Quadratic probing
3. Double hashing
1. Linear probing:
In linear probing, we linearly probe for the next slot. When a col-
lision occurs, that is, when two records demand the same location
in the hash table, then collision can be solved by placing the second
record linearly down wherever the empty location is found.
2. Quadratic probing:
If there is a collision at hash key or address h, quadratic prob-
ing method probes the table at locations h+1, h+4, h+9, ...etc., that is,
h(key)=key % table size gives us hash key, h then if that location is
already flled, then hash key is obtained by h + i^2 where i = 1, 2, .. so
on gives us an iteration number.
300 Data Structures using C
3. Double hashing:
Double hashing uses nonlinear probing by computing different probe
increments for different keys. Double hashing uses two hash functions.
The frst function computes the original address or hash key, and if the
slot is available, save the record at that index, but the slot is not empty,
then calculate hash key second time using the second hash function.
1. Chaining
2. Use of buckets
1. Chaining:
One way of resolving collisions is to maintain n linked lists, one
for each possible address in the hash table. A key k, hashes to an
address i = h (k) in the table. At the address i, we fnd the head of a
list containing all records having keys that have hashed to i. This list
is then searched for a record containing key k.
2. Use of buckets:
Suppose we divide a table into n number of groups of records, with
each group containing exactly m number of records, then each group
of m number of records is called a bucket. The hash function h (k)
computes a bucket number from the element key K, and the record
containing K is stored in the bucket whose bucket number is h (K). If
a particular bucket overfows, an overfow policy is involved.
If a bucket overfows, a chaining technique can be used to link to
an "overfow" bucket. This link can be planted at the end of the over-
fowed bucket. It is convenient to keep overfow buckets on the same
cylinder or we may have a separate cylinder for overfows.
7.9 Sorting
Sorting is a basic operation in computer science. Sorting refers to an operation
of arranging data in any given sequence, that is, in increasing order or
decreasing order.
Searching and Sorting Techniques 301
Sorting
1. Start.
2. Read an entire number of elements from user says, n.
3. Stores all elements in the array, which is entered by the user.
4. Specify i=0 for the frst pass.
5. Compare the adjacent elements, if (a [j] > a [j+1]) then swap the elements.
6. Repeat step 4 for all the elements.
7. The increment value of i by 1 and repeat steps 4 and 5 till the value
of i < n-1.
8. Print the ascending order sorted list of elements.
9. Stop.
1. First pass:
11 No swapping 11 11 11
21 7 swapped 7 7
7 21 21 No swapping 21
35 35 35 6 swapped
2. Second pass:
7 swapped 7 7
11 11 No swapping 11
21 21 6 swapped
3. Third pass:
7 No swapping 7
11 6
6 swapped. Now remaining six elements are also placed at their sorted position.
7 Fourth largest element in the array placed at fourth last position in an array.
11
21
35
Searching and Sorting Techniques 303
All fve-array elements are sorted on the fourth pass. If there are n number
of elements, then the total number of passes required is (n-1).
Output:
Thus, the time complexity of the bubble sort algorithm is O (n2). For bub-
ble sort algorithm, worst case, average-case and best-case time complexity
remains the same, that is, n2.
Space complexity of bubble sort:
O (1) is the space complexity of bubble sort.
21 5 9 2 a
index 0 1 2 3
Here, in the frst pass, fnd the smallest element, that is 2, at index 3. In
addition, 0 index and index 3 are different; then, swap the values of these two
indices that is a [0] which is 21 and a [3] which is 2. Now element 2 is sorted
to its own position. Therefore, after completion of frst pass array, a becomes
as follows:
2 5 9 21 a
index 0 1 2 3
In the second pass, fnd the smallest element in the array a from index 1
to 3. Here 5 is the smallest element in the array a from index 1 to 3. Therefore,
check the index of minimum element and 1, here both are same, so no swap
requires. Now elements 2 and 5 are sorted to their own position. Therefore,
after completion of the second pass array, a becomes as follows:
306 Data Structures using C
2 5 9 21 a
index 0 1 2 3
In a third pass, fnd the smallest element in the array a from index 2 to 3.
Here 9 is the smallest element in the array a from index 2 to 3. Therefore,
check the index of the minimum element and 2, here both are same, so no
swap requires. Now elements 2, 5 and 9 are sorted to their own position.
Therefore, after completion of the third pass array, a becomes as follows in
which all elements are in the sorted position. Here total array elements are
four, so total three passes are required to sort the array:
2 5 9 21 a
index 0 1 2 3
loc=j;
}
}
if(loc!=i)
{
temp=a[i];
a[i]=a[loc];
a[loc]=temp;
}
}
printf("\nArray elements after selection sort:\n");
for(i=0;i<n;i++)
{
printf("%d\t",a[i]);
}
}
Output:
Thus, the time complexity of the selection sort algorithm is O(n2). For the
selection sort algorithm, worst-case, average-case and best-case time com-
plexity remains the same, that is, n2.
Space complexity of selection sort:
O (1) is the space complexity of the selection sort.
308 Data Structures using C
45 -30 170 97 21
a[0] a[1] a[2] a[3] a[4]
Pass 1: First copy a[1] value into temp variable. Compare temp with a[0], if
temp < a[0], then interchange the elements.
-30 45 170 97 21
a[0] a[1] a[2] a[3] a[4]
Pass 2: Now copy a[2] value into temp variable. Compare temp with a[1] and
a[0] if temp > a[1] and a[0], then no need to interchange.
-30 45 170 97 21
position. Again compare temp with a[1], here a[1] < temp so insert the temp
value into the array position a[2].
-30 45 97 170 21
a[0] a[1] a[2] a[3] a[4]
Pass 4: For the next pass, copy a [4] value into temp variable. Then compare
temp with a [3], a [3] > temp, then shift the value of 170 to the a [4] array posi-
tion. Again, comparing a [2] with temp, here a [2] > temp so shift the value 97
to the a [3] array position. Again, comparing a [1] with temp, here a [1] > temp
so shift the value 45 to the a [2] array position. Again, comparing a [0] with
temp, here a [0] < temp so insert the temp value into the array position a [1].
Therefore, in this sort, we have to insert the new value into the already sorted
array so-called as insertion sort. After insertion of value 21 into array posi-
tion a [1], all array elements are sorted in ascending order as shown in the
below fgure.
-30 21 45 97 170
a[0] a[1] a[2] a[3] a[4]
Output:
1. Start.
2. Read the total number of the elements from the user say, n.
312 Data Structures using C
3. Stores all the elements in the array, which is entered by the user.
4. Take the frst element from the array and called it the pivot element.
5. Now fnd all elements, which are less than this pivot element and
place them before the pivot elements.
i. Lesser elements
ii. Pivot elements
iii. Elements greater than the pivot element
6. Repeat steps 3 and 4 each time placing a pivot element at its proper
position. This complete list will get sorted.
7. Stop.
25 57 48 38 10
a[0] a[1] a[2] a[3] a[4]
Pass 1: set a[0], the element that is 25 as the pivot element. Now fnd all the
elements lesser than 25 and place 25 after all lesser elements.
10 25 57 48 38
10 25 48 38 57
sub-list 1 pivot
Pass 3: Again from sub-list 1 48 is a new pivot element. Place all lesser than
48 elements before it.
10 25 38 48 57
sub-list 1 pivot
Here, the sub-list 1 contains only one element and lists having one element
each so stop the algorithm.
Thus, the list is sorted by quick sort.
Searching and Sorting Techniques 313
{
h--;
}
//swap the list[l] and list[h] element
if(l < h)
{
temp = list[l];
list[l] = list[h];
list[h] = temp;
}
} //completion of outer while loop
//swap the element list[pivot] and list[h]
temp = list[pivot];
list[pivot] = list[h];
list[h] = temp;
quickSort(list,low,h-1); //sort left sub-list
quickSort(list,h+1,high); //sort right sub-list
} // completion of if
}
Output:
1. Time effciency of the quick sort depends on the selection of the pivot
element. Inadequately picked pivot element leads to the worst-case
time complexity.
2. Tough to implement a partitioning algorithm in quick sort.
1. Find the central point to partition the array into two halves:
Middle index of array or list, mid = (low + high)/2
2. Call mergeSort for the left or frst half:
Call mergeSort (arr, low, high)
3. Call mergeSort for the right or second half:
Call mergeSort (arr, mid+1, high)
4. Merge the two halves sorted in steps 2 and 3:
Call merge (arr, low, mid, high)
91 -38 48 33 56 25 10 84
a[0] a[1] a[2] a[3] a[4] a[5] a[6] a[7]
Step 1:
The elements are stored in an array, we will go on dividing the array.
91 -38 48 33 56 25 10 84
91 -38 48 33 56 25 10 84
91 -38 48 33 56 25 10 84
Further division is not possible. Hence, we will stop dividing and start
merging.
91 -38 48 33 56 25 10 84
-38 91 33 48 25 56 10 84
Sort it Sort it
-38 33 48 91 10 25 56 84
void merge(int *a, int *t, int low, int mid, int high);
//main function definition
int main()
{
int n, a[10], t[10], l=0, h, i;
printf("Enter size of array:");
scanf("%d", &n);
printf("Enter %d array elements:\n", n);
h=n-1;
for(i=0;i<=(n-1);i++)
{
scanf("%d", &a[i]);
}
printf("Array elements before sorting:\n");
for(i=0;i<=(n-1);i++)
{
printf("%d\t", a[i]);
}
merge_sort(a,t,l,h);
printf("\nArray elements after sorting:\n");
for(i=0;i<=(n-1);i++)
{
printf("%d\t",a[i]);
}
return 0;
}
//function definition for merge sort
void merge_sort(int *a, int *t, int low, int high)
{
int mid;
if(high>low)
{
mid=(high+low)/2; //find the middle array index
merge_sort(a,t,low,mid); //call to the left sub-list till left
sub-list contains only one element
merge_sort(a,t,mid+1,high); // call to the right sub-list till
right sub-list contains only one element
merge(a,t,low,mid+1,high); //call to merge and sort function
}
}
// function definition for merging two sub-lists that are left
and right sub-lists
void merge(int *a, int *t, int low, int mid, int high)
{
//mid is the first element’s index of the right sub-list
//high is the last element’s index of the right sub-list
//pos variable is refers index of temporary array t
// a is the original array
int pos, n, end, i;
pos = low; //low is first element’s index of the left sub-list
Searching and Sorting Techniques 319
high--;
}
}
Output:
1. Merge Sort is useful for sorting the linked list in O (n Log2 n) time.
2. Merge Sort is used in external sorting.
3. Merge Sort is used in e-commerce applications.
1. Creation of heap
2. Processing of heap
1. The binary tree is an almost complete binary tree. That is, each leaf
node in the tree is either at level d or at level d-1 that means the dif-
ference between levels of leaf nodes is only one is permitted. And at
depth d, that is the last level, if a node is present, then all the nodes to
the left of that node should also be present frst, and no gap between
the two nodes from left to the right side of level d.
2. Keys in nodes are arranged such, that content or value of each node
is less than or equal to the content of its father or parent node. Which
means for each node info [i] <= info [j], where j is the father of node i.
This heap is called as max heap.
Here, in heap, each level of binary tree is flled from left to right and a new
node is not placed on a new level until the preceding level is full.
FIGURE 7.7
Examples of a Heap and not a Heap.
1. Start
2. s = i ;
3. Find parent node index of i th node in the array as,
parent = s / 2;
key[ s] = newkey ;
4. while ( s != 0 && key[parent] <= key[s] )
{
Thereafter exchange the parent and the child nodes as,
temp = key [parent] ;
Searching and Sorting Techniques 323
key[parent] = key[s];
keys[s] = temp;
Advance the new node one level up in the tree as
follows,
s = parent;
parent = s / 2 ;
}
5. Stop.
Heap of size 1
Heap of size 2
Heap of size 3
324 Data Structures using C
Heap of size 4
FIGURE 7.8
Creating of a heap of size 6.
Heap of size 5
Heap of size 6
See Figure 7.8.
Index value
0 20
1 15
2 17
3 4
4 10
5 9
FIGURE 7.9
Heap of size 6 is represented using an array.
Searching and Sorting Techniques 325
heap [0] with heap [n – 2], adjusting the array to be a heap of size (n – 2) and
so on. At the end, we get an array that contains the keys in sorted order. The
algorithm to process a heap is as follows:
Algorithm of processing a heap:
Step 1: Start.
Step 2: Interchange the root node with the last node in the heap array.
Step 3: At present, heap [maxnode-1] is in its correct position.
Step 4: Now, compare the new root value with its left child value.
Step 5: If the new root value is smaller than its left child, then compare
the left child with its right sibling. else go to Step 7.
Step 6: If the left child value is larger than its right sibling, then
swap root with the left child. Otherwise, swap root with its right
child.
Step 7: If the root value is larger than its left child, then compare the root
value with its right child value.
Step 8: If the root value is smaller than its right child, then swap root
with the right child. Otherwise, stop the process.
Step 9: Repeat the same until the root node is fxed at its exact position.
Step 10: Repeat the step 2 to 9 for new root till the heap contains one
element.
Step 11: Stop.
Index value
0 4
1 9
2 10
3 15
4 17
5 20
FIGURE 7.10
Heap array of size 6 after processing of heap.
326 Data Structures using C
if(l <= heapSize && A[l] > A[i]) //compare value of left child
with value of parent node
largest = l; //if left child’s value is greater assign left
child index to the largest variable
else
largest = i; //Otherwise parent node’s value is greater,
then assign parent index to largest variable
if(r <= heapSize && A[r] > A[largest]) //compare value of
right child with value of largest index value
//in the array which either parent
node or left child node value
largest = r; //if right child’s value is greater assign
right child index to the largest variable
if(largest != i) //if largest index not equal to parent index
then swap the values of largest element
//with parent node value
{
int temp = A[i];
A[i] = A[largest];
A[largest] = temp;
Heapify(A, largest); //Again recursively check current parent
value with its left and right child value
//till parent node reach to the root node
in the binary tree
}
}
void BuildHeap (int* A)
{
int i; //index of parent node
heapSize = n - 1; //Heap size is (n-1) because array index
start from 0
for(i = (n - 1) / 2; i >= 0; i--)
{
Heapify(A, i); //processing of Heap
}
}
//Heap sort function
void HeapSort (int* A)
{
int i;
BuildHeap(A); //Creating Heap function
Output:
328 Data Structures using C
1. First, consider the creation phase, in this phase, insertion of the key
requires O (log2 i) comparisons and interchange with a maximum of
k other keys along the branch to the root of the heap.
2. If we analyze the processing phase, a heap of size i requires O(log2 i)
comparisons and interchanges even in the worst case.
1 / 2 ˛ log 2i + 1 / 2 ˛ log 2i = O ( n log 2 n )
i = 2 to n i = 2 to n
Thus, in the worst case, time complexity for heap sort is O (n log2 n).
Time complexity of heap sort:
1. The heap sort is very effcient. Heap sort is particularly suitable for
sorting a huge list of items.
2. The heap sort can be implemented as an in-place sorting algorithm.
This means that its memory usage is minimal.
3. The heap sort gives us consistent performance. This means it per-
forms equally well in the best, average and worst cases.
4. The heap sort is simpler to understand than other equally effcient
sorting algorithms because it does not use recursion.
1. A stable sort maintains the relative order of items that have the same
key that is the way they are present in the initial array. Heap sort is
unstable sort. It might rearrange the relative order.
2. In practice, heap sort is slightly worse than quick sort.
Searching and Sorting Techniques 329
24. Explain the algorithm for quick sort and give a suitable example.
25. Write a program to implement quick sort.
26. What are the different types of hashing techniques explain with a
suitable example?
27. What is hashing? Explain collision in hash function with suitable
example?
28. Write a note on types of hash functions?
29. What is open and closed hashing?
30. Discuss collision resolution techniques with examples.
31. Write a note on linear probing and chaining without replacement?
Answer: (A)
Explanation:
External sorting is sort of elements from an external fle by reading
it from secondary memory.
332 Data Structures using C
8. The time complexity analysis of the heap sort in the worst-case sce-
nario is
A. O(n2 log n)
B. O(log n)
C. O(n log n)
D. O(n2 log n2)
Answer: (C)
Explanation:
The worst-case time complexity of heap sort is O (n log n).
9. If the given input array elements are almost sorted in this scenario,
which of the following internal sorting algorithm gives the optimum
performance effciency?
A. Selection sort
B. Bubble sort
C. Heap sort
D. Insertion sort
Answer: (D)
Explanation:
If the given input array elements are almost sorted then the inser-
tion sort algorithm gives you Ω (n) time complexity.
10. What is special algorithm design paradigm is used in the quick sort
and merge sort algorithm?
A. Greedy method paradigm
B. Backtracking paradigm
C. Divide-and-conquer paradigm
D. Dynamic programming paradigm
Answer: (C)
Explanation:
The quick sort and merge sort algorithms are based on the divide-
and-conquer design paradigm.
11. What is the complexity of the search time of the hashing search
method?
A. O (n2)
B. O (logn)
C. O (nlogn)
D. O (1)
Answer: (D)
Explanation:
Searching and Sorting Techniques 333
Since every hash key has a unique array index, requires a constant
time for searching an element from the array.
12. Which of the following is not the technique to avoid collision in
hashing?
A. Linear probing
B. Chaining with replacement
C. Chaining without replacement
D. Dynamic programming
Answer: (D)
Explanation:
Linear probing, chaining with replacement and chaining without
replacement are the techniques to avoid collision in hashing. While
dynamic programming is not the collision avoiding technique.
13. In the chaining technique in hashing, which of the following data
structure is most suitable?
A. Singly linear linked list
B. Doubly linked list
C. Tree
D. Graph
Answer: (B)
Explanation:
In a doubly linked list, deletion of elements from chaining becomes
easier than other data structures, hence a doubly linked list is most
suitable.
14. What is the worst-case time complexity of linear search and binary
search, respectively?
A. O (n log2 n), O(log2 n)
B. O(log2 n), O(n)
C. O(n), O(log2 n)
D. O(1), O(n)
Answer: (C)
Explanation:
The worst-case time complexity of the linear search is O (n) and for
binary search is O (log2 n).
15. The case in which a hash key other than the desired one is kept at the
identifed location is called as?
A. Open hashing
B. Closed hashing
334 Data Structures using C
C. Chaining
D. Collision
Answer: (D)
Explanation:
When a hash function returns the same address or hash key for
more than one record is called a collision.
16. Which of the following data structure is used in hash tables?
A. Queue
B. Doubly linked list
C. Stack
D. Array
Answer: (B)
Explanation:
The linked list data structure is used to organize the data in hash
tables.
17. What is the time complexity of searching, deleting and inserting into
direct addressing in hashing?
A. O(1), O(n), O(1)
B. O(n), O(n), O(1)
C. O(1), O(1), O(1)
D. O(1), O(n), O(n2)
Answer: (C)
Explanation:
Hashing functions such as inserting, deleting and searching opera-
tions can be performed with a constant time complexity equal to O (1).
18. Which of the following sorting technique is called non-linear sorting?
A. Heap sort
B. Bubble sort
C. Insertion sort
D. Quick sort
Answer: (A)
Explanation:
Heap sort is also called a non-linear sorting technique.
19. Which of the following is not an example of a closed hashing or open
addressing method?
A. Linear probing
B. Quadratic probing
C. Double Hashing
D. Chaining
Searching and Sorting Techniques 335
Answer: (D)
Explanation:
Chaining is an example of open hashing or closed addressing
method.
20. What is the quickest search method among the following in the
worst case?
A. Linear searching
B. Binary searching
C. Hashing
D. Sequential search
Answer: (C)
Explanation:
Hashing is the fastest search method as it gives direct addressing
also in the worst case.
21. Which of the following is an example of an open hashing or closed
addressing method?
A. Linear probing
B. Quadratic probing
C. Double Hashing
D. Use of buckets
Answer: (D)
Explanation:
The use of buckets is an example of open hashing or closed
addressing method.
22. What is the space complexity of quick sort and merge sort algorithm?
A. O (n log2 n), O (log2 n)
B. O (log2 n), O (n)
C. O (n), O (log2 n)
D. O (1), O (n)
Answer: (B)
Explanation:
The space complexity of quick sort is O (log2 n) and the merge sort
algorithm having O (n) as space complexity.
References
Alfred V. Aho, John E. Hopcroft, and Jeffrey D. Ullman 2012. Data Structures and
Algorithms. Published by Pearson Education, Bengaluru.
Ellis Horowitz, Sartaj Sahni, and Susan Anderson-Freed 1992. Fundamentals of Data
Structures in C. Published by W. H. Freeman, Macmillan Publishers, New York.
G. S. Baluja 2014. Data Structures through C++ (A Practical Approach). Published by
Dhanpat Rai & Co. (P) Limited, New Delhi.
Kamal Rawat, Meenakshi 2018. Data Structures for Coding Interviews. Published by
BPB Publication, Delhi.
Narasimha Karumanchi 2016. Data Structures and Algorithms Made Easy: Data
Structures and Algorithmic Puzzles. Published by CareerMonk, Hyderabad.
Peter Brass 2008. Advanced data structures. Published by Cambridge University Press,
Cambridge.
Seymour Lipschutz 2014. Data Structures, (Schaum’s Outline Series). Published by
McGraw Hill Education, New York.
Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, and Clifford Stein
2014. Introduction to Algorithms. Published by The MIT Press, Cambridge, MA;
London.
Vibrant Publishers 2016. Data Structures & Algorithms Interview Questions You’ll Most
Likely Be Asked. Published by Vibrant Publishers, Chennai.
Y. Langsam, M. J. Augenstein, and A. M. Tenenbaum 2015. Data Structures Using C and
C+. Published by Pearson Education, Bengaluru.
337
Index
339
340 Index
right subtree 163, 184 string 36, 37, 38, 82, 83, 84
RL rotation 215 strongly connected graph 238, 239
root node 163, 164, 165, 170, 171, 173, 175,
182, 199, 201, 205, 226, 235, 322, terminal node 164, 221
325, 326, 327 time and space complexity 24
rotation 213, 214, 215, 216, 217 top of the stack 6, 28, 30, 31, 62
RR rotation 214 Tower of Hanoi 40
run time 11, 82, 97, 310 tree 163, 164, 165, 166, 167, 168, 170, 171,
172, 173, 175, 181, 192, 215, 216
searching algorithm 204, 288 tree traversal 172
search tree 167, 192, 195, 201, 218, 285
selection sort 305, 306, 307, 308 undirected graph 235, 236, 238, 242, 244,
sequential search 286 265, 266, 267, 272
shortest path 212, 257, 261, 262 union 7, 165, 277
shortest path algorithm 261, 262 unsorted list 324
siblings 164, 225, 226
simple graph 238, 239, 240, 241 vertex 236, 237, 238, 240, 241, 242, 247
Singly Linked List 7, 99, 145, 157 visited 62, 173, 247, 248, 250, 251, 252, 253,
sorted array 212, 309 257, 259, 262, 264, 265, 277
sorted list 286, 292, 301, 316, 324
sorting algorithm 308, 311, 315, 328 weakly connected digraph 238, 239
space complexity 9, 10, 307, 311, 315, weighted graph 245, 266
320, 328 worst case 11, 12, 286, 288, 291, 292,
spanning tree 212, 253, 261, 265, 266, 268, 293, 304, 307, 310, 314, 315, 316,
274, 277 320, 328
stack 6, 7, 8, 9, 24, 27, 28, 29, 30, 31, 34, 35,
36, 37, 38, 52, 62, 63, 134, 257, 258
Taylor & Francis eBooks
www.taylorfrancis.com
Improved
A streamlined A single point search and
experience for of discovery discovery of
our library for all of our content at both
customers eBook content book and
chapter level