Unit I - List, Stack, Queue Updated 26-7-24
Unit I - List, Stack, Queue Updated 26-7-24
E - CSE
UNIT I - LINEAR DATA STRUCTURES – LIST, STACK AND QUEUE
List ADT– Singly Linked Lists – Doubly Linked Lists-Circular Linked List– Applications of Lists : l
Manipulation on Polynomia –Stack ADT –Implementation of Stack – Applications of Stack – Balancing
Symbols - Conversion of Infix to postfix expression – Expression Evaluation - Queue ADT - Circular
Queue – Double Ended Queue – Applications of queues.
Data:
A collection of facts, concepts, figures, observations, occurrences or instructions in a
formalized manner.
Information:
The meaning that is currently assigned to data by means of the conventions applied to
those data(i.e. processed data)
Record:
Collection of related fields.
Data type:
Set of elements that share common set of properties used to solve a program.
Data Structures:
Data Structure is the way of organizing, storing, and retrieving data and their relationship
with each other.
Characteristics of data structures:
1. It depicts the logical representation of data in computer memory.
1.Traversal
2.Search
3.Insertion
4.Deletion
DATA STRUCTURES
TREES GRAPHS
LISTS ARRAYS STACKS QUEUE
Non-Linear Structures:
In non-linear data strucutres, there is definite order or sequence in which data elements are arranged. For
instance, a non-linear data structures could arrange data elements in a hierarchical fashion. Examples of
non-linear data structures are trees and graphs.
Static Ds:
If a ds is created using static memory allocation, ie. ds formed when the number of data items are known
in advance ,it is known as static data static ds or fixed size ds
Dynamic Ds:
If the ds is created using dynamic memory allocation i.e ds formed when the number of data items are not
known in advance is known as dynamic ds or variable size ds.
Compiler design
Operating system
Statistical analysis package
DBMS
Numerical analysis
Simulation
Artificial intelligence
Graphics
An abstract Data type (ADT) is defined as a mathematical model with a collection of operations defined
on that model. Set of integers, together with the operations of union, intersection and set difference form
a example of an ADT. An ADT consists of data together with functions that operate on that data.
Advantages/Benefits of ADT:
1.Modularity
2.Reuse
3.code is easier to understand
4.Implementation of ADTs can be changed without requiring changes to the program that uses the ADTs.
If the element at position i is Ai, then its successor is Ai+1 and its predecessor is Ai-1
Linked Lists:
A Linked list is an ordered collection of elements. Each element in the list is referred as a node. Each
node contains two fields namely,
Data field-The data field contains the actual data of the elements to be stored in the list Next field- The
next field contains the address of the next node in the list
DATA NEXT
To use dynamic memory allocation functions, you must include the header file stdlib.h.
malloc()
The malloc function reserves a block of memory of specified size and returns a pointer of type void. This
means that we can assign it to any type of pointer.
The general syntax of malloc() is ptr =(cast-type*)malloc(byte-size);
where ptr is a pointer of type cast-type. malloc() returns a pointer (of cast type) to an area of memory
with size byte-size.
calloc():
calloc() function is another function that reserves memory at the run time. It is normally used to request
multiple blocks of storage each of the same size and then sets all bytes to zero. calloc() stands for
contiguous memory allocation and is primarily used to allocate memory for arrays. The syntax of calloc()
can be given as:
ptr=(cast-type*) calloc(n,elem-size);
The above statement allocates contiguous space for n blocks each of size elem-size bytes. The only
difference between malloc() and calloc() is that when we use calloc(), all bytes are initialized to zero.
calloc() returns a pointer to the first byte of the allocated region.
free():
The free() is used to release the block of memory.
Syntax:
The general syntax of the free()function is, free(ptr);
where ptr is a pointer that has been created by using malloc() or calloc(). When memory is deallocated
using free(), it is returned back to the free list within the heap.
realloc():
At times the memory allocated by using calloc() or malloc() might be insufficient or in excess. In both
the situations we can always use realloc() to change the memory size already allocated by calloc() and
malloc(). This process is called reallocation of memory. The general syntax for realloc() can be given as,
ptr = realloc(ptr,newsize);
The function realloc() allocates new memory space of size specified by newsize to the pointer variable
ptr. It returns a pointer to the first byte of the memory block. The allocated new block may be or may not
A singly linked list is a linked list in which each node contains only one link field pointing to the next
node in the list
SLL
List L
Null
L
Insert(10,List L)- A new node with data 10 is inserted and the next field is updated to NULL. The next
field of previous node is updated to store the address of new node.
Insert(20,L) - A new node with data 20 is inserted and the next field is updated to NULL. The next field
of previous node is updated to store the address of new node.
10 20 Null
L P
Insert(30,L) - A new node with data 30 is inserted and the next field is updated to NULL. The next field
of previous node is updated to store the address of new node.
10 20 30 Null
L P
NULL
L P
Routine to Find the Element in the List:
This routine returns the position of X in the list L
{
position p;
p=L->next;
while(p!=NULL && p->data!=X)
p=p->next;
return(p);
}
Find(List L, 20) - To find an element X traverse from the first node of the list and move to the next with
the help of the address stored in the next field until data is equal to X or till the end of the list
Find Previous
It returns the position of its predecessor.
{
position p; p = L;
while( p -> next ! = NULL && p -> next -> data! = X )
p = p -> next;
return P;
}
It delete the first occurrence of element X from the list L void Delete( int x , List L){
position p, Temp;
p = FindPrevious( X, L);
if( ! IsLast (p, L))
{
temp = p -> next;
P -> next = temp -> next;
void Delete_list(List L)
{
position P,temp;
P=L->next;
L->next=NULL;
while(P!=NULL)
{
temp=P->next;
free(P);
P=temp;
}
}
Advantages of SLL
1.The elements can be accessed using the next link
Disadvantages of SLL
1.Traversal in the backwards is not possible 2.Less efficient to for insertion and deletion.
Doubly-Linked List
A doubly linked list is a linked list in which each node has three fields namely Data, Next, Prev.
DLL NODE
If we add one more node in the list,then create a newnode and attach that node to the end of the list.
L->next=newnode; newnode->prev=L;
Position p , temp;
P = Find( x, L );
if(P==L->next)
temp=L;
L->next=temp->next;
temp->next->prev=L;
free(temp);
elseif( IsLast( p, L ) )
{
temp = p;
p -> prev -> next = NULL;
free(temp);
}
else
{
void find()
{
int a,flag=0,count=0; if(L==NULL)
printf(“\nThe list is empty”);
else
{
printf(“\nEnter the elements to be searched”);
scanf(“%d”,&a);
for(P=L;P!=NULL;P=P->next)
{
count++;
if(P->data==a)
{
flag=1;
printf(“\nThe element is found”);
printf(“\nThe position is %d”,count);
break;
}
}
Advantages of DLL:
The DLL has two pointer fields. One field is prev link field and another is next link field. Because of
these two pointer fields we can access any node efficiently whereas in SLL only one link field is there
which stores next node which makes accessing of any node difficult.
Disadvantages of DLL:
The DLL has two pointer fields. One field is prev link field and another is next link field. Because of
these two pointer fields, more memory space is used by DLL compared to SLL
Applications of List:
1.Polynomial ADT
2.Radix sort
3.Multilist
Polynomial Manipulation
Polynomial manipulations such as addition, subtraction & differentiation etc.. can be
performed using linked list.
{
newnode -> coeff = ptr1 -> coeff + ptr2 -> coeff;
newnode -> power = ptr1 -> power ;
newnode -> next = NULL;
list3 = create( list3, newnode );
ptr1 = ptr1 -> next;
ptr2 = ptr2 -> next;
}
else if(ptr1 -> power > ptr2 -> power )
{
newnode -> coeff = ptr1 -> coeff;
newnode -> power = ptr1 -> power;
newnode -> next = NULL;
list3 = create( list3, newnode );
ptr1 = ptr1 -> next;
}
else
{
newnode -> coeff = ptr2 -> coeff; newnode -> power = ptr2 -> power;
newnode -> next = NULL;
list3 = create( list3, newnode );
ptr2 = ptr2 -> next;
}}}
Polynomial Differentiation:
void diff()
{
poly *ptr1, *newnode; ptr1 = list1;
while( ptr1 != NULL)
{
newnode = (struct poly*)malloc( sizeof (struct poly));
newnode->coeff=(ptr1-coeff)*(ptr1->power);
newnode->power=ptr1->power-1;
newnode->next=NULL;
list3=create(list3,newnode);
ptr1=ptr1->next;
}
}
Polynomial Multiplication
void mul()
{
poly *ptr1, *ptr2, *newnode ; ptr1= list1;
ptr2 = list2;
{
newnode -> coeff = ptr1 -> coeff * ptr2 -> coeff;
newnode -> power = ptr1 -> power+ptr2->power;
newnode -> next = NULL;
list3 = create( list3, newnode );
ptr1 = ptr1 -> next;
ptr2 = ptr2 -> next;
}
}
}
STACK
Stack is a Linear Data Structure that follows Last In First Out(LIFO) principle.
Insertion and deletion can be done at only one end of the stack called TOP of the stack.
Example: - Pile of coins, stack of trays
STACK ADT
STACK MODEL
TOP pointer
It will always point to the last element inserted in the stack. For empty stack, top will be pointing to -1.
Two fundamental operations performed on the stack are PUSH and POP.
(b) POP:
1. Stack Overflow
An Attempt to insert an element X when the stack is Full, is said to be stack overflow.
For every Push operation, we need to check this condition.
2. Stack Underflow:
An Attempt to delete an element when the stack is empty, is said to be stack underflow.
For every Pop operation, we need to check this condition.
Implementation of Stack
Header
30 20 10 NULL
40
newnode
Before Insertion
Header
40 30 20 10 NULL
After Insertion
TOP
(i) Pop Operation
It is the process of deleting the Top element of the stack.
With Linked List implementations, the element at the Front of the List (i.e.)
S -> next is always deleted.
It takes only one parameter. Pop(X).The element X to be deleted from the Front of the List.
Before deleting the front element in the list, check for Empty Stack.
If the Stack is Empty, deletion is not possible.
Otherwise, make the front element in the list as “temp”.
Update the next field of header.
Header
40 30 20 10 NULL
TOP
Before Deletion
Header
40 30 20 10 NULL
HEADER
30 20 10 NULL
TOP
After Deletion
if(S->next==NULL)
error(“Stack is empty”);
return 0;
else
return S->next->data;
}
R INSTITUTE OF TECHNOLOGY II YEAR/III SEM B.E-CSE
S
Header
40 30 20 10 NULL
Applications of Stack
INFIX:
The arithmetic operator appears between the two operands to which it is being applied.
TOP
R INSTITUTE OF TECHNOLOGY II YEAR/III SEM B.E-CSE
POSTFIX:
The arithmetic operator appears directly after the two operands to which it applies. Also called reverse
polish notation.
PREFIX:
The arithmetic operator is placed before the two operands to which it applies. Also called polish notation.
Read the infix expression one character at a time until it encounters the delimiter “#” Step 1: If the
Step 2: If the character is an operator, push it onto the stack. If the stack operator has a higher or equal
priority than input operator then pop that operator from the stack and place it onto the output.
Step 3:If the character is left parenthesis, push it onto the stack
Step 4:If the character is a right parenthesis, pop all the operators from the stack till it encounters left
parenthesis, discard both the parenthesis in the output.
Infix: A+B*C/(E-F)#
A+B*C/(E-F) A
A+B*C/(E-F) A +
R INSTITUTE OF TECHNOLOGY II YEAR/III SEM B.E-CSE
Input String Output Stack Operator Stack
A+B*C/(E-F) AB +
A+B*C/(E-F) AB +*
A+B*C/(E-F) ABC +*
A+B*C/(E-F) ABC* +/
A+B*C/(E-F) ABC*EF- +/
A+B*C/(E-F) ABC*EF-/+
Towers of Hanoi
Towers of Hanoi can be easily implemented using recursion. Objective of the problem is moving
a collection of N disks of decreasing size from one pillar to another pillar. The movement of the disk is
restricted by the following rules.
Rule 2 : No larger disk could ever reside on a pillar on top of a smaller disk.
Rule 3 : A 3rd pillar could be used as an intermediate to store one or more disks, while they were being
A B C
R INSTITUTE OF TECHNOLOGY II YEAR/III SEM B.E-CSE
Step 2. If N = 2, move the 1st disk from A to B. Then move the 2nd disk from A to C, The move the 1st
disk from B to C.
Step 3. If N = 3, Repeat the step (2) to more the first 2 disks from A to B using C as intermediate. Then
the 3rd disk is moved from A to C. Then repeat the step (2) to move 2 disks from B to C using A as
intermediate.
In general, to move N disks. Apply the recursive technique to move N - 1 disks from A to B using C as
an intermediate. Then move the Nth disk from A to C. Then again apply the recursive technique to move
N - 1 disks from B to C using A as an intermediate.
Tower 1
R INSTITUTE OF TECHNOLOGY II YEAR/III SEM B.E-CSE
Since disks are moved from each tower in a LIFO manner, each tower may be considered as a
Stack. Least Number of moves required solving the problem according to our algorithm is given by,
O(N)=O(N-1)+1+O(N-1) =2N-1
Function Calls
When a call is made to a new function all the variables local to the calling routine need to be
saved, otherwise the new function will overwrite the calling routine variables. Similarly the current
location address in the routine must be saved so that the new function knows where to go after it is
completed.
Call
balance()
int fact(int n)
{
int S;
if(n==1)
return(1);
else
S = n * fact( n – 1 );
return(S)
}
Compilers check the programs for errors, a lack of one symbol will cause an error.
R INSTITUTE OF TECHNOLOGY II YEAR/III SEM B.E-CSE
A Program that checks whether everything is balanced.
Every right parenthesis should have its left parenthesis.
Check for balancing the parenthesis brackets braces and ignore any other character.
((B*B)-{4*A*C}/[2*A]) #
( (
(
R INSTITUTE OF TECHNOLOGY II YEAR/III SEM B.E-CSE
)
(
{
(
{
[ (
]
(
Empty stack, hence the symbols the balanced in the given expression.
R INSTITUTE OF TECHNOLOGY II YEAR/III SEM B.E-CSE
Example for unbalanced symbols:
QUEUES:
Queue is a Linear Data Structure that follows First in First out (FIFO) principle.
Insertion of element is done at one end of the Queue called “Rear “end of the Queue.
Deletion of element is done at other end of the Queue called “Front “end of the Queue.
Example: - Waiting line in the ticket counter.
Front End
RearEnd
QUEUE Q
Deletion Insertion
R INSTITUTE OF TECHNOLOGY II YEAR/III SEM B.E-CSE
Queue Model
Front Pointer:-
Rear Pointer:-
It always points to the last element inserted in the Queue.
Front (F) = - 1
Rear (R) = - 1
Operations on Queue
It is the process of inserting a new element at the rear end of the Queue.
For every EnQueue operation
o Check for Full Queue
o If the Queue is full, Insertion is not possible.
o Otherwise, increment the rear end by 1 and then insert the element in the rear end
of the Queue.
It is the process of deleting the element from the front end of the queue.
For every DeQueue operation
o Check for Empty queue
o If the Queue is Empty, Deletion is not possible.
o Otherwise, delete the first element inserted into the queue and then increment the
R INSTITUTE OF TECHNOLOGY II YEAR/III SEM B.E-CSE
front by 1.
Exceptional Conditions of Queue
Queue Overflow
Queue Underflow
An Attempt to insert an element X at the Rear end of the Queue when the Queue is full is said to
be Queue overflow.
For every Enqueue operation, we need to check this condition.
Implementation of Queue
Queue can be implemented in two ways.
Header
10 20 30 40 NULL
Front Rear
struct node;
typedef struct node * Queue;
typedef struct node * position;
int IsEmpty (Queue Q);
Queue CreateQueue (void);
void MakeEmpty (Queue Q);
void Enqueue (int X, Queue Q);
void Dequeue (Queue Q);
struct node
{
int data ;
position next;
}* Front = NULL, *Rear = NULL;
Empty Queue
R INSTITUTE OF TECHNOLOGY II YEAR/III SEM B.E-CSE
{ Q
Header NULL
if ( Q Next = = NULL)
return (1);
It is the process of inserting a new element at the Rear end of the Queue.
It takes two parameters, EnQueue ( int X , Queue Q ). The elements X to be inserted into the
Queue Q.
Using malloc ( ) function allocate memory for the newnode to be inserted into the Queue.
If the Queue is Empty, the newnode to be inserted will become first and last node in the list.
Hence Front and Rear points to the newnode.
Otherwise insert the newnode in the Rear -> next and update the Rear pointer.
R INSTITUTE OF TECHNOLOGY II YEAR/III SEM B.E-CSE
newnode data = X;
newnode next = NULL;
Rear next = newnode;
Rear = newnode;
}
Header
20 30 40 NULL
Front Rear
Applications of Queue
1. Serving requests on a single shared resource, like a printer, CPU task scheduling etc.
2. In real life, Call Center phone systems will use Queues, to hold people calling them in an order,
until a service representative is free.
3. Handling of interrupts in real-time systems. The interrupts are handled in the same order as they
arrive, First come first served.
4. Batch processing in operating system.
5. Job scheduling Algorithms like Round Robin Algorithm uses Queue.
With the array implementation of Queue, the element can be deleted logically only by moving
Front = Front + 1.
Here the Queue space is not utilized fully.
CIRCULAR QUEUE
enqueue(data)
Create a struct node type node.
Insert the given data in the new node data section and NULL in address section.
If Queue is empty then initialize front and rear from new node.
Queue is not empty then initialize rear next and rear from new node.
New node next initialize from front
dequeue()
Check if queue is empty or not.
If queue is empty then dequeue is not possible.
Else Initialize temp from front.
If front is equal to the rear then initialize front and rear from null.
Print data of temp and free temp memory.
If there is more than one node in Queue then make front next to front then initialize rear next
from front.
struct node
{
int data;
struct node *next;
};
void display ()
{
struct node *temp;
temp = front;
if ((front == NULL) && (rear == NULL))
printf ("\nQueue is Empty");
else
{
do
{
printf (" %d", temp->data);
temp = temp->next;
}
while (temp != front);
}
}
Dequeue is also called as double ended queue and it allows user to perform insertion and deletion from
the front and rear position. And it can be easily implemented using doubly linked list. On creating
dequeue, we need to add two special nodes at the ends of the doubly linked list (head and tail). And these
two nodes needs to be linked between each other (initially).
In DEQUE, insertion and deletion operations are performed at both ends of the Queue.
Operations on Deque :
struct node
{
int data;
struct node *prev, *next;
};
{
struct node *newnode = (struct node *)malloc(sizeof (struct node));
newnode->data = data;
newnode->next = newnode->prev = NULL;
return (newnode);
}
void createSentinels()
{
head = createNode(0);
tail = createNode(0);
head->next = tail;
tail->prev = head;
}
temp = head->next;
head->next = newnode;
newnode->prev = head;
newnode->next = temp;
temp->prev = newnode;
}
void dequeueAtFront()
{
struct node *temp;
if (head->next == tail) {
printf("Queue is empty\n");
} else {
temp = head->next;
head->next = temp->next;
temp->next->prev = head;
free(temp);
}
return;
}
void dequeueAtRear()
{
struct node *temp;
if (tail->prev == head) {
printf("Queue is empty\n");
} else {
temp = tail->prev;
tail->prev = temp->prev;
23CS1302 47 DATA STRUCTURE
PANIMALAR ENGINEERING COLLEGE II YEAR/III SEM B.E-CSE
temp->prev->next = tail;
free(temp);
}
return;
}
if (head->next == tail)
{
printf("Queue is empty\n");
return;
}
temp = head->next;
while (temp != tail) {
printf("%-d", temp->data);
temp = temp->next;
}
printf("\n");
}