Professional Documents
Culture Documents
Unit-2 Complete Notes
Unit-2 Complete Notes
Unit-2 Complete Notes
Linear data structures are commonly used for organising and manipulating data in a
sequential fashion. Some of the most common linear data structures include:
An Abstract Data Type (ADT) is a programming concept that defines data structure,
without specifying the implementation details. In other words, it is a blueprint for
creating a data structure that defines the behaviour without specifying how it is
implemented.
The process of providing only the essentials and hiding the details is known as
abstraction.
The user of data type does not need to know how that data type is implemented, for
example, we have been using Primitive values like int, float, char data types only with the
knowledge that these data type can operate and be performed on without any idea of how
they are implemented.
So a user only needs to know what a data type can do, but not how it will be
implemented. ADT hides the inner structure and design of the data type.
Now we’ll define three ADTs namely List ADT, Stack ADT, Queue ADT.
1. List ADT
Vies of list
2. Stack ADT
View of stack
View of Queue
Abstract data types (ADTs) have several advantages and disadvantages that should be
considered when deciding to use them in software development. Here are some of the main
advantages and disadvantages of using ADTs:
Advantages:
Encapsulation: ADTs provide a way to encapsulate data and operations into a single
unit, making it easier to manage and modify the data structure.
Abstraction: ADTs allow users to work with data structures without having to know
the implementation details, which can simplify programming and reduce errors.
Data Structure Independence: ADTs can be implemented using different data
structures, which can make it easier to adapt to changing needs and requirements.
Information Hiding: ADTs can protect the integrity of data by controlling access and
preventing unauthorized modifications.
Modularity: ADTs can be combined with other ADTs to form more complex data
structures, which can increase flexibility and modularity in programming.
Disadvantages:
Overhead: Implementing ADTs can add overhead in terms of memory and
processing, which can affect performance.
Complexity: ADTs can be complex to implement, especially for large and complex
data structures.
Learning Curve: Using ADTs requires knowledge of their implementation and
usage, which can take time and effort to learn.
Limited Flexibility: Some ADTs may be limited in their functionality or may not be
suitable for all types of data structures.
Cost: Implementing ADTs may require additional resources and investment, which
can increase the cost of development.
Stack
A stack is an abstract data type (ADT) which is used to store data in a linear(sequential) way.
A stack only has a single end (which is stack's top) through which we can insert or delete data
from it.
There are many different stack operations which can be applied on a stack.
Operations in stack:
A stack follows a Last in, First out principle (LIFO). This means the data inserted in the stack
last will be first to be removed. Also, the data is inserted or deleted through the stack top.
Given below is the stack representation to show how data is inserted and deleted in a stack.
Stack Operations
There are various stack operations that are applicable on a stack. Stack operations are
generally used to extract information and data from a stack data structure.
1. push()
Push is a function in stack definition which is used to insert data at the stack's top.
2. pop()
Pop is a function in the stack definition which is used to remove data from the stack's top.
3. topElement() / peek()
TopElement / Peek is a function in the stack which is used to extract the element present at
the stack top.
4. isEmpty()
isEmpty is a boolean function in stack definition which is used to check whether the stack is
empty or not. It returns true if the stack is empty. Otherwise, it returns false.
5. isFull()
isFull is a function which is used to check whether the stack has reached its maximum limit
of insertion of data or not i.e. if 'maxLimit' is the maximum number of elements that can be
stored in the stack and if there are exactly maxLimit number of elements present in the stack
currently, then the function isFull() returns true. Otherwise, if the number of elements present
in the stack currently are less than 'maxLimit', then isFull() returns false.
6. size()
Size is a function in stack definition which is used to find out the number of elements that are
present inside the stack.
In array implementation, the stack is formed by using the array. All the operations regarding
the stack are performed using arrays.
Push operation
Adding an element into the top of the stack is referred to as push operation. Push operation
involves following two steps.
1. Increment the variable Top so that it can now refer to the next memory location.
2. Add element at the position of incremented top. This is referred to as adding new
element at the top of the stack.
Stack is overflown when we try to insert an element into a completely filled stack therefore,
our main function must always avoid stack overflow condition.
begin
if stack is full
return
endif
else
increment top
stack[top] assign value
end else
end procedure
Deletion of an element from the top of the stack is called pop operation. The value of the
variable top will be incremented by 1 whenever an item is deleted from the stack. The top
most element of the stack is stored in an another variable and then the top is decremented by
1. the operation returns the deleted value that was stored in another variable as the result.
The underflow condition occurs when we try to delete an element from an already empty
stack.
Algorithm for pop of stack:
begin
if stack is empty
return
endif
else
store value of stack[top]
decrement top
return value
end else
end procedure
Peek operation involves returning the element which is present at the top of the stack without
deleting it. Underflow condition can occur if we try to return the top element in an already
empty stack.
Begin
if top = -1 then stack empty
item = stack[top]
return item
End
Application of Stack in real life:
CD/DVD stand.
Stack of books in a book shop.
Call center systems.
Undo and Redo mechanism in text editors.
The history of a web browser is stored in the form of a stack.
Call logs, E-mails, and Google photos in any gallery are also stored in form of a stack.
YouTube downloads and Notifications are also shown in LIFO format(the latest appears
first ).
Allocation of memory by an operating system while executing a process.
Queue:
1. A queue can be defined as an ordered list which enables insert operations to be performed
at one end called REAR and delete operations to be performed at another end
called FRONT.
3. For example, people waiting in line for a rail ticket form a queue.
Applications of Queue
Due to the fact that queue performs actions on first in first out basis which is quite fair for the
ordering of actions. There are various applications of queues discussed as below.
1. Queues are used as buffers in most of the applications like MP3 media player, CD
player, etc.
2. Queue are used to maintain the play list in media players in order to add and remove
the songs from the play-list.
3. Queues are used in operating systems for handling interrupts.
4. Queues are widely used as waiting lists for a single shared resource like printer, disk,
CPU.
5. Queues are used in asynchronous transfer of data for eg. pipes, file IO, sockets.
Queue
Queue is the data structure that is similar to the queue in the real world. A queue is a data
structure in which whatever comes first will go out first, and it follows the FIFO (First-In-
First-Out) policy. Queue can also be defined as the list or collection in which the insertion is
done from one end known as the rear end or the tail of the queue, whereas the deletion is
done from another end known as the front end or the head of the queue.
The real-world example of a queue is the ticket queue outside a cinema hall, where the person
who enters first in the queue gets the ticket first, and the last person enters in the queue gets
the ticket at last. Similar approach is followed in the queue in data structure.
Types of Queue
There are four different types of queue that are listed as follows -
In Linear Queue, an insertion takes place from one end while the deletion occurs from
another end. The end at which the insertion takes place is known as the rear end, and the end
at which the deletion takes place is known as front end. It strictly follows the FIFO rule.
Circular Queue
In Circular Queue, all the nodes are represented as circular. It is similar to the linear Queue
except that the last element of the queue is connected to the first element. It is also known as
Ring Buffer, as all the ends are connected to another end. The representation of circular
queue is shown in the below image -
Priority Queue
It is a special type of queue in which the elements are arranged based on the priority. It is a
special type of queue data structure in which every element has a priority associated with it.
Suppose some elements occur with the same priority, they will be arranged according to the
FIFO principle. The representation of priority queue is shown in the below image
In Deque or Double Ended Queue, insertion and deletion can be done from both ends of the
queue either from the front or rear. It means that we can insert and delete elements from both
front and rear ends of the queue.
Operations performed on queue
The fundamental operations that can be performed on queue are listed as follows -
o Enqueue: The Enqueue operation is used to insert the element at the rear end of the
queue. It returns void.
o Dequeue: It performs the deletion from the front-end of the queue. It also returns the
element which has been removed from the front-end. It returns an integer value.
o Peek: This is the third operation that returns the element, which is pointed by the
front pointer in the queue but does not delete it.
o Queue overflow (isfull): It shows the overflow condition when the queue is
completely full.
o Queue underflow (isempty): It shows the underflow condition when the Queue is
empty, i.e., no elements are in the Queue.
We can easily represent queue by using linear arrays. There are two variables i.e. front and
rear, that are implemented in the case of every queue. Front and rear variables point to the
position from where insertions and deletions are performed in a queue. Initially, the value of
front and queue is -1 which represents an empty queue. Array representation of a queue
containing 5 elements along with the respective values of front and rear, is shown in the
following figure.
The above figure shows the queue of characters forming the English word "HELLO". Since,
No deletion is performed in the queue till now, therefore the value of front remains -1 .
However, the value of rear increases by one every time an insertion is performed in the
queue. After inserting an element into the queue shown in the above figure, the queue will
look something like following. The value of rear will become 5 while the value of front
remains same.
After deleting an element, the value of front will increase from -1 to 0. however, the queue
will look something like following.
Algorithm to insert any element in a queue
Check if the queue is already full by comparing rear to max - 1. if so, then return an overflow
error.
If the item is to be inserted as the first element in the list, in that case set the value of front
and rear to 0 and insert the element at the rear end.
Otherwise keep increasing the value of rear and insert each element one by one having rear as
the index.
Circular Queue
There was one limitation in the array implementation of Queue. If the rear reaches to the end
position of the Queue then there might be possibility that some vacant spaces are left in the
beginning which cannot be utilized. So, to overcome such limitations, the concept of the
circular queue was introduced.
The following are the operations that can be performed on a circular queue:
o Front: It is used to get the front element from the Queue.
o Rear: It is used to get the rear element from the Queue.
o enQueue(value): This function is used to insert the new value in the Queue. The new
element is always inserted from the rear end.
o deQueue(): This function deletes an element from the Queue. The deletion in a
Queue always takes place from the front end.
Enqueue operation
The steps of enqueue operation are given below:
o If rear!= max-1, then rear will be incremented to mod(maxsize) and the new value
will be inserted at the rear end of the queue.
o If front!= 0 and rear = max-1, it means that queue is not full, then set the value of
rear to 0 and insert the new element there.
There are two cases in which the element cannot be inserted:
o When front ==0 && rear = max-1, which means that front is at the first position of
the Queue and rear is at the last position of the Queue.
o front== rear + 1;
Step1:IF(REAR+1)%MAX=FRONT
Write "OVERFLOW"
Goto step4
[End OF IF]
Step 2:IF FRONT = -1 and REAR = -1
SET FRONT = REAR = 0
ELSE IF REAR = MAX - 1 and FRONT ! = 0
SET REAR = 0
ELSE
SET REAR = (REAR + 1) % MAX
[END OF IF]
Step 3:SET QUEUE[REAR] = VAL
Step 4:EXIT
Dequeue Operation
o First, we check whether the Queue is empty or not. If the queue is empty, we cannot
perform the dequeue operation.
o When the element is deleted, the value of front gets decremented by 1.
o If there is only one element left which is to be deleted, then the front and rear are reset
to -1.
Step 4: EXIT
Let's understand the enqueue and dequeue operation through the diagrammatic
representation.
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.
o Every element in a priority queue has some priority associated with it.
o An element with the higher priority will be deleted before the deletion of the lesser
priority.
o If two elements in a priority queue have the same priority, they will be arranged using
the FIFO principle.
1, 3, 4, 8, 14, 22
All the values are arranged in ascending order. Now, we will observe how the priority queue
will look after performing the following operations:
o Dequeue (): This function will remove the highest priority element from the priority
queue. In the above priority queue, the '1' element has the highest priority, so it will be
removed from the priority queue.
o Enqueue(2): This function will insert '2' element in a priority queue. As 2 is the
smallest element among all the numbers so it will obtain the highest priority.
o Dequeue (): It will remove '2' element from the priority queue as it has the highest
priority queue.
o Enqueue (5): It will insert 5 element after 4 as 5 is larger than 4 and lesser than 8, so
it will obtain the third highest priority in a priority queue.
o 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.
Step 1:It removes the element with the highest priority. So, define two variables index
and highestPriority and iterate over the entire array elements. The variable index stores
the index of the element having the highest priority so far, and the variable
highestPriority stores the priority of arr[index].
Step2:At the end of the iteration, since we need to delete the element with the highest
priority, so left shift all the elements after the position “index” by one position and
finally decrement size by 1.
Step 1: It just returns the element with the highest priority. So, define two variables
index and highestPriority and iterate over the entire array elements.
Step2: The variable index stores the index of the element having the highest priority so
far and the variable highestPriority stores the priority of arr[index].
Space Complexity
O(n), where n is the maximum number of elements that can be stored in the priority queue.
Recursion
The process in which a function calls itself is called recursion. Using a recursive algorithm,
certain problems can be solved quite easily.
Recursive Algorithm
A recursive algorithm is a problem-solving approach that involves breaking down a problem
into smaller and smaller sub-problems until the sub-problems become simple enough to be
solved directly. The solution to the original problem is then obtained by combining the
solutions to the smaller sub-problems.
A key feature of a recursive algorithm is that it calls itself with a smaller version of the
problem as its input. The algorithm uses a base case to terminate the recursion when the
problem is small enough that it can be solved directly without further recursion.
For example, consider the factorial function. The factorial of a non-negative integer n
(denoted as n!) is the product of all positive integers from 1 to n. This function is solved as
follows:
factorial(n):
if n == 0:
return 1
else:
return n * factorial(n-1)
Step 1- Start with defining a recursive function along with all necessary parameters.
Step 2- Determine a base condition. In that base condition, either it will return a specific
value or end the recursive function.
Step 3- If the base case condition is not met, it will break down the large complex problem
into subproblems to reduce its size.
Step 4- The same function recursively calls itself. If there are multiple recursive calls made,
then they are combined to solve the original problem.
Step 5- Defining the termination condition is essential so that it does not create an infinite
recursion.