B.C.A Sem 2 DS
B.C.A Sem 2 DS
Primitive data structure will contain some value, i.e., it cannot be NULL.
Integer: The integer data type contains the numeric values. It contains the whole
numbers that can be either negative or positive. When the range of integer data type is not
large enough then in that case, we can use long.
Float: The float is a data type that can hold decimal values. When the precision of
decimal value increases then the Double data type is used.
Boolean: It is a data type that can hold either a True or a False value. It is mainly used
for checking the condition.
Character: It is a data type that can hold a single character value both uppercase and
lowercase such as 'A' or 'a'.
A linear data structure is a structure in which the elements are stored sequentially, and the
elements are connected to the previous and the next element. As the elements are stored
sequentially, so they can be traversed or accessed in a single run. The implementation of linear
data structures is easier as the elements are sequentially organized in memory. The data elements
in an array are traversed one after another and can access only one element at a time.
The types of linear data structures are Array, Queue, Stack, Linked List.
Array: An array consists of data elements of a same data type. For example, if we want
to store the roll numbers of 10 students, so instead of creating 10 integer type variables,
we will create an array having size 10. Therefore, we can say that an array saves a lot of
memory and reduces the length of the code.
Stack: It is linear data structure that uses the LIFO (Last In-First Out) rule in which the
data added last will be removed first. The addition of data element in a stack is known as
a push operation, and the deletion of data element form the list is known as pop
operation.
Queue: It is a data structure that uses the FIFO rule (First In-First Out). In this rule, the
element which is added first will be removed first. There are two terms used in the queue
front end and rear The insertion operation performed at the back end is known ad
enqueue, and the deletion operation performed at the front end is known as dequeue.
Linked list: It is a collection of nodes that are made up of two parts, i.e., data element
and reference to the next node in the sequence.
A non-linear data structure is also another type of data structure in which the data elements are
not arranged in a contiguous manner. As the arrangement is nonsequential, so the data elements
cannot be traversed or accessed in a single run. In the case of linear data structure, element is
connected to two elements (previous and the next element), whereas, in the non-linear data
structure, an element can be connected to more than two elements.
Tree
It is a non-linear data structure that consists of various linked nodes. It has a hierarchical tree
structure that forms a parent-child relationship. The diagrammatic representation of a tree data
structure is shown below:
Graph
A graph is a non-linear data structure that has a finite number of vertices and edges, and these
edges are used to connect the vertices. The vertices are used to store the data elements, while the
edges represent the relationship between the vertices. A graph is used in various real-world
problems like telephone networks, circuit networks, social networks like LinkedIn, Facebook. In
the case of facebook, a single user can be considered as a node, and the connection of a user with
others is known as edges.
Stack
A Stack is a linear data structure that follows the LIFO (Last-In-First-Out) principle.
Stack has one end, whereas the Queue has two ends (front and rear).
It contains only one pointer top pointer pointing to the topmost element of the stack.
Whenever an element is added in the stack, it is added on the top of the stack, and the element can be
deleted only from the stack. In other words, a stack can be defined as a container in which insertion
and deletion can be done from the one end known as the top of the stack.
Working of Stack
Stack works on the LIFO pattern. As we can observe in the below figure there are five memory
blocks in the stack; therefore, the size of the stack is 5.
Suppose we want to store the elements in a stack and let's assume that stack is empty. We have
taken the stack of size 5 as shown below in which we are pushing the elements one by one until
the stack becomes full.
since our stack is full as the size of the stack is 5. In the above cases, we can observe that it goes from
the top to the bottom when we were entering the new element in the stack. The stack gets filled up
from the bottom to the top. When we perform the delete operation on the stack, there is only one way
for entry and exit as the other end is closed. It follows the LIFO pattern, which means that the value
entered first will be removed last. In the above case, the value 5 is entered first, so it will be removed
only after the deletion of all the other elements.
push(): When we insert an element in a stack then the operation is known as a push. If the stack
is full then the overflow condition occurs.
pop(): When we delete an element from the stack, the operation is known as a pop. If the stack
is empty means that no element exists in the stack, this state is known as an underflow state.
isEmpty(): It determines whether the stack is empty or not.
isFull(): It determines whether the stack is full or not.'
peek(): It returns the element at the given position.
count(): It returns the total number of elements available in a stack.
change(): It changes the element at the given position.
display(): It prints all the elements available in the stack.
PUSH operation
POP operation
Before deleting the element from the stack, we check whether the stack is empty.
If we try to delete the element from the empty stack, then the underflow condition occurs.
If the stack is not empty, we first access the element which is pointed by the top
Once the pop operation is performed, the top is decremented by 1, i.e., top=top-1.
Types of Stacks:
Fixed Size Stack: As the name suggests, a fixed size stack has a fixed size and cannot grow or
shrink dynamically. If the stack is full and an attempt is made to add an element to it, an
overflow error occurs. If the stack is empty and an attempt is made to remove an element from
it, an underflow error occurs.
Dynamic Size Stack: A dynamic size stack can grow or shrink dynamically. When the stack is full,
it automatically increases its size to accommodate the new element, and when the stack is
empty, it decreases its size. This type of stack is implemented using a linked list, as it allows for
easy resizing of the stack.
Stack also helps in implementing function call in computers. The last called function is always
completed first.
Stacks are also used to implement the undo/redo operation in text editor.
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
struct Stack {
int top;
unsigned capacity;
int* array;
};
of
// stack as 0
stack->capacity = capacity;
stack->top = -1;
return stack;
if (isFull(stack))
return;
stack->array[++stack->top] = item;
if (isEmpty(stack))
return INT_MIN;
return stack->array[stack->top--];
if (isEmpty(stack))
return INT_MIN;
return stack->array[stack->top];
void main()
push(stack, 10);
push(stack, 20);
push(stack, 30);
getch();
return 0;
The recursion use the stack implementation. The stack is a data structure which can be
manipulated by pushing (adding) and popping(removing) data of the top of the list. In fact, the
stack stands for LIFO or Last In First Out
So, when a function is called, this one go to the top of the stack. And then, as the operation of a
stack requires, the function at the top of the stack will be the first to be executed. This means that
the last function called will be the first one executed.
We must consider when a function requests space for local variables, the allocated space is added
to the top of the stack. So when the end of the function is reached, the space allocated for local
variables appears at the top of the stack.
Therefore, we must bear in mind that variables that are stored in stack-based memory cannot be
dynamically allocated pieces of memory during program execution. Instead, memory of this type
uses a heap-based storage allocation.
It is important to note that stack overflow can occur due to limited space available for stack-based
memory. One of the most common causes of stack overflow is infinite recursion, a behavior that we
must consider when programming recursive functions.
Recursion VS Iteration
SR
Recursion Iteration
No.
Terminates when the condition
1) Terminates when the base case becomes true.
becomes false.
2) Used with functions. Used with loops.
Every recursive call needs extra space in the Every iteration does not require any
3)
stack memory. extra space.
4) Smaller code size. Larger code size.
Example
#include <stdio.h>
int fib(int n)
// Stop condition
if (n == 0)
return 0;
// Stop condition
if (n == 1 || n == 2)
return 1;
// Recursion function
else
// Driver Code
void main()
// Initialize variable n.
int n = 5;
int i;
getch();
return 0;
Polish Notation:- The process of writing the operators either before or after the
operands in known as polish notation. It has 3 categories:
1. Infix : Operators are written between two operands.
2. Prefix: operators are written before their operands.
3. Postfix: Operators are written after their operands.(RPN= reverse polish
notation)
Example:
Infix: a+b*c
Prefix: +a*bc
Postfix: abc*+
Example
3+4+3
Sr No Expression Stack Postfix
0 3 3
1 + + 3
2 4 + 34
3 + + 34+
4 3 + 34+3
5 34+3+
3+(4+3)
5+6/(6-2)*{9-3}
Queue
A Queue is defined as a linear data structure that is open at both ends and the operations are
performed in First In First Out (FIFO) order.
For example, people waiting in line for a rail ticket form a queue.
Applications of Queue
Queues are widely used as waiting lists for a single shared resource like printer, disk, CPU.
Queues are used in asynchronous transfer of data (where data is not being transferred at the
same rate between two processes) for eg. pipes, file IO, sockets.
Queues are used as buffers in most of the applications like MP3 media player, CD player, etc.
enqueue(): Inserts an element at the end of the queue i.e. at the rear end.
dequeue(): This operation removes and returns an element that is at the
front end of the queue.
front(): This operation returns the element at the front end without
removing it.
rear(): This operation returns the element at the rear end without
removing it.
isEmpty(): This operation indicates whether the queue is empty or not.
isFull(): This operation indicates whether the queue is full or not.
size(): This operation returns the size of the queue i.e. the total number of
elements it contains.
Types of Queues:
Simple Queue: Simple queue also known as a linear queue is the most basic
version of a queue. Here, insertion of an element i.e. the Enqueue
operation takes place at the rear end and removal of an element i.e. the
Dequeue operation takes place at the front end. Here problem is that if we
pop some item from front and then rear reach to the capacity of the queue
and although there are empty spaces before front means the queue is not
full but as per condition in isFull() function, it will show that the queue is
full then. To solve this problem we use circular queue.
Priority Queue: This queue is a special type of queue. Its specialty is that it
arranges the elements in a queue based on some priority. The priority can
be something where the element with the highest value has the priority so
it creates a queue with decreasing order of values. The priority can also be
such that the element with the lowest value gets the highest priority so in
turn it creates a queue with increasing order of values. In pre-define
priority queue, C++ gives priority to highest value whereas Java gives
priority to lowest value.
For implementing queue, we need to keep track of two indices, front and rear. We enqueue an
item at the rear and dequeue an item from the front. If we simply increment front and rear
indices, then there may be problems, the front may reach the end of the array. The solution to
this problem is to increase front and rear in circular manner.
Example
#include<stdio.h>
#include<stdlib.h>
#define maxsize 5
void insert();
void delete();
void display();
int queue[maxsize];
void main ()
int choice;
while(choice != 4)
printf("\n*************************Main Menu*****************************\n");
printf("\n=================================================================\n");
scanf("%d",&choice);
switch(choice)
case 1:
insert();
break;
case 2:
delete();
break;
case 3:
display();
break;
case 4:
exit(0);
break;
default:
getch();
void insert()
int item;
scanf("\n%d",&item);
if(rear == maxsize-1)
printf("\nOVERFLOW\n");
return;
front = 0;
rear = 0;
else
rear = rear+1;
queue[rear] = item;
void delete()
int item;
printf("\nUNDERFLOW\n");
return;
else
item = queue[front];
if(front == rear)
front = -1;
rear = -1 ;
else
front = front + 1;
void display()
int i;
if(rear == -1)
printf("\nEmpty queue\n");
else
for(i=front;i<=rear;i++)
printf("\n%d\n",queue[i]);
Circular queue
A circular queue is similar to a linear queue as it is also based on the FIFO (First In First Out) principle
except that the last position is connected to the first position in a circular queue that forms a circle. It is
also known as a Ring Buffer.
enQueue(value): This function is used to insert the new value in the Queue. The new element is
always inserted from the rear end.
deQueue(): This function deletes an element from the Queue. The deletion in a Queue always
takes place from the front end.
Memory management: The circular queue provides memory management. As we have already
seen that in linear queue, the memory is not managed very efficiently. But in case of a circular
queue, the memory is managed efficiently by placing the elements in a location which is unused.
CPU Scheduling: The operating system also uses the circular queue to insert the processes and
then execute them.
Traffic system: In a computer-control traffic system, traffic light is one of the best examples of
the circular queue. Each light of traffic light gets ON one by one after every jinterval of time. Like
red light gets ON for one minute then yellow light for one minute and then green light. After
green light, the red light gets ON.
Enqueue operation
Step 4: EXIT
Dequeue Operation
First, we check whether the Queue is empty or not. If the queue is empty, we cannot perform
the dequeue operation.
When the element is deleted, the value of front gets decremented by 1.
If there is only one element left which is to be deleted, then the front and rear are reset to -1.
Step 1: IF FRONT = -1
Write " UNDERFLOW "
Goto Step 4
[END of IF]
Step 4: EXIT
diagrammatic representation.
Example
#include <stdio.h>
# define max 6
int front=-1;
int rear=-1;
empty
front=0;
rear=0;
queue[rear]=element;
full
printf("Queue is overflow..");
else
int dequeue()
empty
printf("\nQueue is underflow..");
else if(front==rear)
front=-1;
rear=-1;
else
front=(front+1)%max;
void display()
int i=front;
else
while(i<=rear)
printf("%d,", queue[i]);
i=(i+1)%max;
void main()
scanf("%d", &choice);
switch(choice)
case 1:
scanf("%d", &x);
enqueue(x);
break;
case 2:
dequeue();
break;
case 3:
display();
}}
getch();
return 0;
Deques
The deque stands for Double Ended Queue. Deque is a linear data structure where the insertion
and deletion operations are performed from both ends. We can say that deque is a generalized
version of the queue.
Though the insertion and deletion in a deque can be performed on both ends, it does not follow
the FIFO rule. The representation of a deque is given as follows -
Types of deque
In input restricted queue, insertion operation can be performed at only one end, while deletion
can be performed from both ends.
In output restricted queue, deletion operation can be performed at only one end, while insertion
can be performed from both ends.
Insertion at front
Insertion at rear
Deletion at front
Deletion at rear
If the queue is empty, both rear and front are initialized with 0. Now, both will point to
the first element.
Otherwise, check the position of the front if the front is less than 1 (front < 1), then
reinitialize it by front = n - 1, i.e., the last index of the array.
If the queue is empty, both rear and front are initialized with 0. Now, both will point to the
first element.
Otherwise, increment the rear by 1. If the rear is at last index (or size - 1), then instead of
increasing it by 1, we have to make it equal to 0
in this operation, the element is deleted from the front end of the queue. Before implementing the
operation, we first have to check whether the queue is empty or not.
If the queue is empty, i.e., front = -1, it is the underflow condition, and we cannot perform the
deletion. If the queue is not full, then the element can be inserted from the front end by using the
below conditions –
If the deque has only one element, set rear = -1 and front = -1.
Else if front is at end (that means front = size - 1), set front = 0.
If the queue is empty, i.e., front = -1, it is the underflow condition, and we cannot perform the
deletion.
If the deque has only one element, set rear = -1 and front = -1.
Applications of deque
Deque can be used as both stack and queue, as it supports both operations.
Deque can be used as a palindrome checker means that if we read the string from both ends,
the string would be the same.
Example
#include <stdio.h>
#define size 5
int deque[size];
void insert_front(int x)
printf("Overflow");
f=r=0;
deque[f]=x;
else if(f==0)
f=size-1;
deque[f]=x;
else
f=f-1;
deque[f]=x;
void insert_rear(int x)
printf("Overflow");
r=0;
deque[r]=x;
else if(r==size-1)
r=0;
deque[r]=x;
else
r++;
deque[r]=x;
void display()
int i=f;
while(i!=r)
printf("%d ",deque[i]);
i=(i+1)%size;
printf("%d",deque[r]);
void getfront()
printf("Deque is empty");
else
void getrear()
printf("Deque is empty");
else
void delete_front()
printf("Deque is empty");
else if(f==r)
f=-1;
r=-1;
else if(f==(size-1))
f=0;
else
f=f+1;
void delete_rear()
printf("Deque is empty");
else if(f==r)
f=-1;
r=-1;
else if(r==0)
r=size-1;
else
r=r-1;
void main()
insert_front(20);
insert_front(10);
insert_rear(30);
insert_rear(50);
insert_rear(80);
delete_front();
delete_rear();
getch();
Priority queue
A priority queue is an abstract data type that behaves similarly to the normal queue except that
each element has some priority, i.e., the element with the highest priority would come first in a
priority queue. The priority of the elements in a priority queue will determine the order in which
elements are removed from the priority queue.
The priority queue supports only comparable elements, which means that the elements are either
arranged in an ascending or descending order.
For example, suppose we have some values like 1, 3, 4, 8, 14, 22 inserted in a priority queue
with an ordering imposed on the values is from least to the greatest. Therefore, the 1 number
would be having the highest priority while 22 will be having the lowest priority.
Every element in a priority queue has some priority associated with it.
An element with the higher priority will be deleted before the deletion of the lesser
priority.
If two elements in a priority queue have the same priority, they will be arranged using the
FIFO principle.
Ascending order priority queue: In ascending order priority queue, a lower priority number is
given as a higher priority in a priority. For example, we take the numbers from 1 to 5 arranged in
an ascending order like 1,2,3,4,5; therefore, the smallest number, i.e., 1 is given as the highest
priority in a priority queue.
Descending order priority queue: In descending order priority queue, a higher priority number
is given as a higher priority in a priority. For example, we take the numbers from 1 to 5 arranged
in descending order like 5, 4, 3, 2, 1; therefore, the largest number, i.e., 5 is given as the highest
priority in a priority queue.
Example
#include <stdio.h>
#include <stdlib.h>
#define MAX 10
//priority queue
void create_queue();
void insert_element(int);
void delete_element(int);
void check_priority(int);
void display_priorityqueue();
int pqueue[MAX];
void main()
int n, choice;
printf("\nEnter 4 to exit");
create_queue();
while (1)
scanf("%d", &choice);
switch(choice)
case 1:
scanf("%d",&n);
insert_element(n);
break;
case 2:
scanf("%d",&n);
delete_element(n);
break;
case 3:
display_priorityqueue();
break;
case 4:
exit(0);
default:
void create_queue()
printf("\nQUEUE OVERFLOW");
return;
front++;
rear++;
pqueue[rear] = data;
return;
else
check_priority(data);
rear++;
int i,j;
pqueue[i] = data;
return;
pqueue[i] = data;
int i;
printf("\nEmpty Queue");
return;
if (data == pqueue[i])
pqueue[i] = -99;
rear--;
if (rear == -1)
front = -1;
return;
void display_priorityqueue()
return;
front = 0;