Unit-I DS Data Structures
Unit-I DS Data Structures
Introduction to Data Structures, abstract data types, Linear list – singly linked list implementation,
insertion, deletion and searching operations on linear list, Stacks- Operations, array and linked
representations of stacks, stack applications, Queues- operations, array and linked representations.
Data Structure is a way to store and organize data so that it can be used efficiently. The data structure as
the name indicates is used for organizing the data in memory.
There are many ways of organizing the data in the memory, one of the data structures which we already
aware is array. Array is a collection of memory elements in which data is stored sequentially, i.e., one
after another. In other words, we can say that array stores the elements in a contiguous manner.
Some examples of Data Structures are Arrays, Linked Lists, Stack, Queue, Trees, etc. Data Structures
are widely used in almost every aspect of Computer Science, i.e., Compiler Design, Operating Systems,
Graphics, Artificial Intelligence, and many more.
Data Structures are the main part of many Computer Science Algorithms as they allow the programmers
to manage the data in an effective way. It plays a crucial role in improving the performance of a program
or software, as the main objective of the software is to store and retrieve the user's data as fast as
possible.
Entities with similar attributes form an Entity Set. Each attribute of an entity set has a range of values,
the set of all possible values that could be assigned to the specific attribute.
o Information: The term "information" is sometimes utilized for data with given attributes of
meaningful or processed data.
o Field: A single elementary unit of information symbolizing the Attribute of an Entity is known as
Field.
o Record: A collection of different data items are known as a Record. For example, if we talk about the
employee entity, then its name, id, address, and job title can be grouped to form the record for the
employee.
o File: A collection of different Records of one entity type is known as a File. For example, if there are
100 employees, there will be 25 records in the related file containing data about each employee.
Need for Data Structures
As applications are becoming more complex and the amount of data is increasing every day, which may
lead to problems with data searching, processing speed, multiple requests handling, and many more.
Data Structures support different methods to organize, manage, and store data efficiently. With the help
of Data Structures, we can easily traverse the data items. Data Structures provide Efficiency, Reusability,
and Abstraction.
A Tree
Mr. Mohammed Afzal, Asst. Professor in CSE (AI&ML) @ SPHN
Email: [email protected], Mob: 8179700193
Trees can be classified into different types:
Binary Tree: A Tree data structure where each parent node can have at most two children is termed a
Binary Tree.
Binary Search Tree: A Binary Search Tree is a Tree data structure where we can easily maintain a
sorted list of numbers.
AVL Tree: An AVL Tree is a self-balancing Binary Search Tree where each node maintains extra
information known as a Balance Factor whose value is either -1, 0, or +1.
B-Tree: A B-Tree is a special type of self-balancing Binary Search Tree where each node consists of
multiple keys and can have more than two children.
2. Graphs
A Graph is another example of a Non-Linear Data Structure comprising a finite number of nodes or
vertices and the edges connecting them.
The Graphs are utilized to address problems of the real world in which it denotes the problem area as a
network such as social networks, circuit networks, and telephone networks. For instance, the nodes or
vertices of a Graph can represent a single user in a telephone network, while the edges represent the link
between them via telephone.
The Graph data structure, G is considered a mathematical structure comprised of a set of vertices, V and
a set of edges, E as shown below:
G = (V, E)
Mr. Mohammed Afzal, Asst. Professor in CSE (AI&ML) @ SPHN
Email: [email protected], Mob: 8179700193
A Graph
The above figure represents a Graph having seven vertices A, B, C, D, E, F, G, and ten edges [A, B], [A,
C], [B, C], [B, D], [B, E], [C, D], [D, E], [D, F], [E, F], and [E, G].
Depending upon the position of the vertices and edges, the Graphs can be classified into different types:
Null Graph: A Graph with an empty set of edges is termed a Null Graph.
Trivial Graph: A Graph having only one vertex is termed a Trivial Graph.
Simple Graph: A Graph with neither self-loops nor multiple edges is known as a Simple Graph.
Multi Graph: A Graph is said to be Multi if it consists of multiple edges but no self-loops.
Pseudo Graph: A Graph with self-loops and multiple edges is termed a Pseudo Graph.
Non-Directed Graph: A Graph consisting of non-directed edges is known as a Non-Directed Graph.
Directed Graph: A Graph consisting of the directed edges between the vertices is known as a
Directed Graph.
Connected Graph: A Graph with at least a single path between every pair of vertices is termed a
Connected Graph.
Disconnected Graph: A Graph where there does not exist any path between at least one pair of
vertices is termed a Disconnected Graph.
Regular Graph: A Graph where all vertices have the same degree is termed a Regular Graph.
Complete Graph: A Graph in which all vertices have an edge between every pair of vertices is
known as a Complete Graph.
Cycle Graph: A Graph is said to be a Cycle if it has at least three vertices and edges that form a
cycle.
Cyclic Graph: A Graph is said to be Cyclic if and only if at least one cycle exists.
Acyclic Graph: A Graph having zero cycles is termed an Acyclic Graph.
Finite Graph: A Graph with a finite number of vertices and edges is known as a Finite Graph.
o Linked list contains two parts, and both are of different types, i.e., one is the simple variable (data),
while another is the pointer variable (next). We can declare the linked list by using the user-defined
data type structure (self-referential structure).
o In the above declaration, a structure named as node is defined that contains two variables, one
is data that is of integer type, and another one is next that is a pointer which contains the address of
next node.
Advantages of Linked list
The advantages of using the Linked list are as follows –
o Dynamic data structure - The size of the linked list may vary according to the requirements. Linked
list does not have a fixed size.
o Insertion and deletion - Unlike arrays, insertion, and deletion in linked list is easier. Array elements
are stored in the consecutive location, whereas the elements in the linked list are stored at a random
location. To insert or delete an element in an array, we have to shift the elements for creating the space.
Whereas, in linked list, instead of shifting, we just have to update the address of the pointer of the
node.
o Memory efficient - The size of a linked list can grow or shrink according to the requirements, so
memory consumption in linked list is efficient.
o Implementation - We can implement both stacks and queues using linked list.
Disadvantages of Linked list
The limitations of using the Linked list are as follows –
o Memory usage - In linked list, node occupies more memory than array. Each node of the linked list
occupies two types of variables, i.e., one is a simple variable, and another one is the pointer variable.
o Traversal - Traversal is not easy in the linked list. If we have to access an element in the linked list,
we cannot access it randomly, while in case of array we can randomly access it by index. For
Node Declaration
Head Declaration
newNode Creation
2. Make the next (link) part of the newNode pointing to the existing first node of the list.
C Function for inserting a newNode at the beginning of the Singly Linked List
3. Since, newNode is the only node that will be inserted in the list, make this node pointed by the head
pointer of the list.
2. Allocate the space for the newNode by using malloc statement in C. Set up data part of the
newNode.
4. At the end of the loop, the temp will be pointing to the last node of the list. Since, the newNode is
going to be the last node of the list, make the next part of this node to point the NULL. Make the
next part of the temp node (which is currently the last node of the list) point to the newNode.
Algorithm for inserting a newNode at the end of the Singly Linked List
Step 1: IF newNode == NULL
WRITE Overflow
GOTO Step 8
C Function for inserting a newNode at the end of the Singly Linked List
2. Allocate the space for the newNode and add the item to the data part of it.
3. Since, at the end of the above loop, the temp pointer would be pointing to the node after which the
newNode will be inserted. Therefore, the next part of the newNode must contain the address of the
next part of the temp (since, newNode will be in between temp and the next of the temp).
4. Make the next part of the temp to point the newNode. This will insert the newNode at the specified
position.
Algorithm for inserting a newNode after a specified Node in singly linked list
Step 1: IF newNode == NULL
WRITE Overflow
GOTO Step 10
END OF IF
Step 2: newNode → data = item
Step 3: SET temp = head
Step 4: SET I = 0
C Function for inserting a newNode after a specified Node in singly linked list
2. free the temp pointer which was pointing to the head node of the list.
2. Now, just need to make the pointer temp2 to point NULL and the last node of the list that is pointed
by temp1 will become free.
Algorithm for deleting a node in singly linked list from the end
Step 1: IF head == NULL
WRITE Underflow
GOTO Step 8
[END OF IF]
Step 2: SET temp1 = head
Step 3: REPEAT Steps 4 and 5 WHILE temp1->next != NULL
Step 4: SET temp2 = temp1
Step 5: SET temp1 = temp1->next
[END OF LOOP]
Step 6: SET temp2->next = NULL
Step 7: FREE temp1
Mr. Mohammed Afzal, Asst. Professor in CSE (AI&ML) @ SPHN
Email: [email protected], Mob: 8179700193
Step 8: EXIT
C Function for deleting a node in singly linked list from the end
2. Make the next of temp2 (points to the specified node) point to the next of temp1 (the node which is
to be deleted). And then free the temp1.
Algorithm for deleting a node after the specified node from singly linked list
Step 1: IF head == NULL
WRITE Underflow
GOTO Step 10
END OF IF
Step 2: SET temp1 = head
Step 3: SET I = 0
Step 4: REPEAT Step 5 TO 8 UNTIL I < loc
Step 5: temp2 = temp1
Step 6: temp1 = temp1 → next
Step 7: IF temp == NULL
WRITE "Desired node not present"
GOTO Step 12
END OF IF
Step 8: I = I+1
END OF LOOP
Step 9: temp2 → next = temp1 → next
Step 10: FREE temp1
C Function for deleting a node after the specified node from singly linked list
o When new items were entering the stack. The stack gets filled up from the bottom to the top.
o When deletion operation is performed on the stack, as 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.
o In the above case, the value 1 is entered first, so it will be removed only after the deletion of all the
other elements.
Standard Stack Operations
The following are some common operations implemented on the stack:
o 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.
o The top most node in the stack always contains the address of the top most node in the stack.
o Lets discuss the way in which, each operation is performed in linked list implementation of stack.
Adding a node to the stack (Push operation)
o Adding a node to the stack is referred to as push operation. Pushing an element to a stack in linked
list implementation is different from that of an array implementation.
o No need to check the Overflow condition in linked list implementation of stack. As memory we are
allocating dynamically.
Mr. Mohammed Afzal, Asst. Professor in CSE (AI&ML) @ SPHN
Email: [email protected], Mob: 8179700193
o In order to push an element onto the stack, the following steps are involved.
1. Create a node first and allocate memory to it.
2. If the SLL is empty (top==NULL) then the item is to be pushed as the start node of the list. This
includes assigning value to the data part of the node and assign null to the address part of the node.
3. If there are some nodes in the list already, then we have to add the new element in the beginning of
the list (to not violate the property of the stack). For this purpose, assign the address of the starting
element to the address field of the new node and make the new node, the starting node of the list.
1. Check for the underflow condition: The underflow condition occurs when we try to pop from an
already empty stack. The stack will be empty if the top pointer of the list points to NULL.
2. Adjust the head pointer accordingly: In stack, the elements are popped only from one end, therefore,
the value stored in the top pointer must be deleted and the node must be freed. The next node of the
top node now becomes the new top node.
2. Move the temp pointer through all the nodes of the list and print the value field attached to every
node.
Postfix notation
A postfix expression is said to be an expression in which the operator appears after the operands.
Syntax of postfix notation is given below:
<operand> <operand> <operator>
For example: AB+ CD+*
Some key points regarding the postfix expression are:
o In postfix expression, operations are performed in the order in which they have written from left to
right.
o It does not any require any parenthesis.
o We do not need to apply operator precedence rules and associativity rules.
In the algebraic expression, the order of the operator precedence is given in the below table:
Operators Symbols
Parenthesis ( ), {}, [ ]
Exponents ^
Multiplication and Division *, /
Addition and Subtraction +,-
Applications of Queue:
Queue is used when things don’t have to be processed immediately, but have to be processed in First
In First Out order like Breadth First Search.
This property of Queue makes it also useful in following kind of scenarios.
TYPES OF QUEUES
There are four different types of queues –
As it is clear from the above image that, the rear is at the last position of the Queue and front is pointing
somewhere rather than the 0th position. In the above array, there are only two elements and other three
positions are empty. The rear is at the last position of the Queue; if we try to insert the element then it will
show that there are no empty spaces in the Queue. There is one solution to avoid such wastage of memory
space by shifting both the elements at the left and adjust the front and rear end accordingly. It is not a
practically good approach because shifting all the elements will consume lots of time. The efficient approach
to avoid the wastage of the memory is to use the circular queue data structure.
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.
Operations on Circular Queue
The following are the operations that can be performed on a circular queue:
o peekFront: It is used to get the front element from the Queue.
o peekRear: 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.
Enqueue operation
The steps of enqueue operation are given below:
o First, we will check whether the Queue is full or not.
o Initially the front and rear are set to -1. When we insert the first element in a Queue, front and rear
both are set to 0.
o When we insert a new element, the rear gets incremented, i.e., rear=rear+1.
Scenarios for inserting an element
There are two scenarios in which queue is not full:
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;
Dequeue Operation
The steps of dequeue operation are given below:
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.
Priority Queue
o 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.
o The priority queue supports only comparable elements, which means that the elements are either
arranged in an ascending or descending order.
o 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.
Characteristics of a Priority queue
A priority queue is an extension of a queue that contains the following characteristics:
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.
Types of Priority Queue
There are two types of 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.
Types of deque
There are two types of deque -
o Input restricted queue
o Output restricted queue
Check empty
This operation is performed to check whether the deque is empty or not. If front == -1, it means that the
deque is empty.
Check full
This operation is performed to check whether the deque is full or not. If front == rear + 1, or front == 0 and
rear == max - 1 it means that the deque is full.
Applications of deque
o Deque can be used as both stack and queue, as it supports both operations.
o Deque can be used as a palindrome checker means that if we read the string from both ends, the string
would be the same.