0% found this document useful (0 votes)
6 views

UNIT 3 C Programming

Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
6 views

UNIT 3 C Programming

Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 41

III

3.2 Linear Data Structures


Figure 3.1 shows the ADT model. There are two types of models in the ADT
model, i.e., the public function and the private function. The ADT model also contains
the data structures that we are using in a program. In this model, first encapsulation is
performed, i.e., all the data is wrapped in a single unit, i.e., ADT. Then, the abstraction is
performed means showing the operations that can be performed on the data structure and
what are the data structures that we are using in a program
LINEAR DATA STRUCTURES
Abstract Data Types (ADTs) – List ADT – Array-Based Implementation – Linked List –
Doubly-Linked Lists – Circular Linked List – Stack ADT – Implementation of Stack –
Applications – Queue ADT – Priority Queues – Queue Implementation – Applications.

3.1 ABSTRACT DATA TYPES (ADTS)


➢ An abstract data type is an abstraction of a data structure that provides only the
interface to which the data structure must adhere. The interface does not give any
specific details about something should be implemented or in what programming
language.
➢ In other words, we can say that abstract data types are the entities that are
definitions of data and operations but do not have implementation details. In this
Fig 3.1 Abstract Data Type Model
case, we know the data that we are storing and the operations that can be
performed on the data, but we don't know about the implementation details. Example 3.1
➢ The reason for not having implementation details is that every programming
Suppose we have an index array of size 4. We have an index location starting from
language has a different implementation strategy for example; a C data structure
is implemented using structures while a C++ data structure is implemented using 0, 1, 2, 3. Array is a data structure where the elements are stored in a contiguous location.
objects and classes. The memory address of the first element is 1000, second element is 1004, third element
is 1008, and the fourth element is 1012. Since it is of integer type so it will occupy 4 bytes
3.1.1 Abstract data type model and the difference between the addresses of each element is 4 bytes. The values stored in
Abstraction: It is a technique of hiding the internal details from the user and only an array are 10, 20, 30 and 40. These values, index positions and the memory addresses
showing the necessary details to the user. are the implementations.
Encapsulation: It is a technique of combining the data and the member function in a The abstract or logical view of the integer array can be stated as:
single unit is known as encapsulation. ➢ It stores a set of elements of integer type.
➢ It reads the elements by position, i.e., index.
➢ It modifies the elements by index
➢ It performs sorting
C Programming and Data Structures 3.3 3.4 Linear Data Structures

3.2 LIST ADT it will get appended after the float value object having value '8.56'. And we can
add repeating values to these list-objects.
➢ The list can be defined as an abstract data type in which the elements are stored
3.2.1 Operations on the List Data Structure
in an ordered manner for easier and efficient retrieval of the elements. List Data
Structure allows repetition that means a single piece of data can occur more than Add or Insert Operation:
once in a list. In the Add or Insert operation, a new item (of any data type) is added in the List
➢ In the case of multiple entries of the same data, each entry of that repeating data Data Structure or Sequence object.
is considered as a distinct item or entry. It is very much similar to the array but Replace or reassign Operation:
the major difference between the array and the list data structure is that array In the Replace or reassign operation, the already existing value in the List object
stores only homogenous data in them whereas the list (in some programming is changed or modified. In other words, a new value is added at that particular index of
languages) can store heterogeneous data items in its object. List Data Structure is the already existing value.
also known as a sequence.
Delete or remove Operation:
➢ The list can be called Dynamic size arrays, which means their size increased as
we go on adding data in them and we need not to pre-define a static size for the In the Delete or remove operation, the already present element is deleted or
list removed from the Dictionary or associative array object.

For example, Find or Lookup or Search Operation:


numbers = [ 1, 2, 3, 4, 5] In the Find or Lookup operation, the element stored in that List Data Structure or
Sequence object is fetched.
➢ In this example, 'numbers' is the name of the List Data Structure object and it has
five items stored in it. In the object named numbers, we have stored all the
3.3 ARRAY-BASED IMPLEMENTATION
elements of numeric type. In the list, the indexing starts from zero, which means
➢ Arrays are defined as the collection of similar types of data items stored at
if we want to access or retrieve the first element of this list then we need to use
contiguous memory locations.
index zero and similarly whenever we want to access any element from this list
named numbers. In other words, we can say that element 1 is on the index 0 and ➢ It is one of the simplest data structures where each data element can be randomly
element 2 is on index 1 and similarly for further all elements. accessed by using its index number.
➢ They are the derived data types in C programming that can store the primitive type
Mixed_data = [205, ‘Mathu’, 8.56]
of data such as int, char, double, float, etc.
➢ In this second example, mixed_data is the name of the list object that stores the
➢ For example, if we want to store the marks of a student in 6 subjects, then we don't
data of different types. In the mixed_data list, we have stored data of three types,
need to define a different variable for the marks in different subjects. Instead, we
first one is the integer type which is id '205', after the integer data we have stored
can define an array that can store the marks in each subject at the contiguous
a string type data having the value ‘Mathu’ stored at index 1 and at last the index
memory locations.
value 2, we have stored a float type data having the value '8.56'.
➢ To access the elements of the mixed_data list, we need to follow the same 3.3.1 Properties of array
approach as defined in the previous example. ➢ Each element in an array is of the same data type and carries the same size that is
➢ And we can add more data to these defined List objects and that will get appended 4 bytes.
at the last of the list. For example, if we add another data in the mixed_data list,
C Programming and Data Structures 3.5 3.6 Linear Data Structures
➢ Elements in the array are stored at contiguous memory locations from which the
first element is stored at the smallest memory location.
➢ Elements of the array can be randomly accessed since we can calculate the address
of each element of the array with the given base address and the size of the data
element.

3.3.2 Representation of an array


➢ Array can be represented in various ways in different programming languages. As
an illustration, let's see the declaration of array in C language
Fig. 3.3: Memory allocation of an array

3.3.4 Access an element from the array


The information given below are required to access any random element from the array
➢ Base Address of the array.
Fig. 3.2: Illustration of an Array ➢ Size of an element in bytes.
As per the above illustration of array, there are some of the following important points - ➢ Type of indexing, array follows.
➢ Index starts with 0. The formula to calculate the address to access an array element
➢ The array's length is 10, which means we can store 10 elements. Byte address of element A[i] = base address + size * ( i - first index)
➢ Each element in the array can be accessed via its index. Here, size represents the memory taken by the primitive data types. As an instance, int
takes 2 bytes, float takes 4 bytes of memory space in C programming.
3.3.3 Memory allocation of an array
➢ Data elements of an array are stored at contiguous locations in the main memory. Example 3.2
The name of the array represents the base address or the address of the first Suppose an array, A[-10 ..... +2 ] having Base address (BA) = 999 and size of an
element in the main memory. Each element of the array is represented by proper element = 2 bytes, find the location of A[-1].
indexing.
L(A[-1]) = 999 + 2 x [(-1) - (-10)]
➢ We can define the indexing of an array in the below ways
= 999 + 18
 0 (zero-based indexing): The first element of the array will be arr[0].
= 1017
 1 (one-based indexing): The first element of the array will be arr[1].
 n (n - based indexing): The first element of the array can reside at any random 3.3.5 Basic operations of an Array
index number Basic operations supported in the array
➢ Fig 3.3 shows the memory allocation of an array arr of size 5. The array follows ➢ Traversal - This operation is used to print the elements of the array.
a 0-based indexing approach. The base address of the array is 100 bytes. It is the ➢ Insertion - It is used to add an element at a particular index.
address of arr[0]. Here, the size of the data type used is 4 bytes; therefore, each ➢ Deletion - It is used to delete an element from a particular index.
element will take 4 bytes in the memory.
➢ Search - It is used to search an element using the given index or by the value.
C Programming and Data Structures 3.7 3.8 Linear Data Structures
➢ Update - It updates an element at a particular index. ➢ There will be wastage of memory if we store less number of elements than the
declared size.
3.3.6 Complexity of Array operations
Time and space complexity of various array operations are described below. 3.4 LINKED LIST
Time Complexity ➢ Linked list is a linear data structure that includes a series of connected nodes.
➢ Linked list can be defined as the nodes that are randomly stored in the memory.
Operation Average Case Worst Case
➢ A node in the linked list contains two parts, i.e., first is the data part and second is
Access O(1) O(1)
the address part.
Search O(n) O(n) ➢ The last node of the list contains a pointer to the null.
Insertion O(n) O(n) ➢ After array, linked list is the second most used data structure.
Deletion O(n) O(n) ➢ In a linked list, every link contains a connection to another link

Space Complexity 3.4.1 Representation of a Linked list


➢ Linked list can be represented as the connection of nodes in which each node
In array, space complexity for worst case is O(n).
points to the next node of the list. The representation of the linked list is shown
3.3.7 Limitations of Array below.
➢ The size of the array must be known in advance before using it in the program.
➢ Increasing the size of the array is a time taking process. It is almost impossible to
expand the size of the array at run time.
➢ All the elements in the array need to be contiguously stored in the memory.
Inserting an element in the array needs shifting of all its predecessors.

3.3.8 Advantages of Array


➢ Arrays are good for storing multiple values in a single variable. Fig. 3.4: Representation of Linked List
➢ Traversing an array is a very simple process; we just need to increment the base
3.4.2 Why use linked list over array?
address of the array in order to visit each element one by one.
➢ Linked list is a data structure that overcomes the limitations of arrays (Refer 3.3.6)
➢ Any element in the array can be directly accessed by using the index.
➢ It allocates the memory dynamically. All the nodes of the linked list are non-
➢ Sorting and searching a value in an array is easier.
contiguously stored in the memory and linked together with the help of pointers.
➢ Arrays are best to process multiple values quickly and easily.
➢ In linked list, size is no longer a problem since we do not need to define its size at
3.3.9 Disadvantages of Array the time of declaration.
➢ Array is homogenous. It means that the elements with similar data type can be ➢ List grows as per the program's demand and limited to the available memory
stored in it. space.
➢ In array, there is static memory allocation that is size of an array cannot be altered.
C Programming and Data Structures 3.9 3.10 Linear Data Structures

3.4.3 Declare a linked list 3.4.4.2 Doubly Linked List


➢ Doubly linked list is a complex type of linked list
➢ It is simple to declare an array, as it is of single type, while the declaration of
➢ Here, a node contains a pointer to the previous as well as the next node in the
linked list is a bit more typical than array. Linked list contains two parts, and both
sequence.
are of different types, i.e.,
➢ Therefore, in a doubly-linked list, a node consists of three parts:
 Simple variable,
 Node data,
 Pointer variable.
 Pointer to the next node in sequence (next pointer), and
We can declare the linked list by using the user-defined data type structure.
 Pointer to the previous node (previous pointer).
The declaration of linked list is given as follows
struct node 3.4.4.3 Circular Singly Linked List
{ ➢ In a circular singly linked list, the last node of the list contains a pointer to the first
node of the list.
int data;
➢ We can have circular singly linked list as well as circular doubly linked list.
struct node *next;
} 3.4.4.4 Circular Doubly Linked List
In the above declaration, we have defined a structure named as node that contains ➢ Circular doubly linked list is a more complex type of data structure.
two variables, one is data that is of integer type, and another one is next that is a pointer ➢ Here a node contains pointers to its previous node as well as the next node.
which contains the address of next node.
➢ Circular doubly linked list doesn't contain NULL in any of the nodes.
3.4.4 Types of Linked list ➢ The last node of the list contains the address of the first node of the list.
Linked list is classified into the following types ➢ The first node of the list also contains the address of the last node in its previous
➢ Singly-Linked List pointer.
➢ Doubly Linked List 3.4.5 Advantages of Linked list
➢ Circular Singly Linked List
➢ Dynamic data structure - The size of the linked list may vary according to the
➢ Circular Doubly Linked List requirements. Linked list does not have a fixed size.
3.4.4.1 Singly-Linked List ➢ Insertion and deletion - Unlike arrays, insertion, and deletion in linked list is
➢ Singly linked list can be defined as the collection of an ordered set of elements. easier. Elements in the linked list are stored at a random location.
➢ A node in the singly linked list consists of two parts: data part and link part. ➢ Memory efficient - The size of a linked list can grow or shrink according to the
requirements, so memory consumption in linked list is efficient.
➢ Data part of the node stores actual information that is to be represented by the
node ➢ Implementation - We can implement both stacks and queues using linked list.
➢ Link part of the node stores the address of its immediate successor.
C Programming and Data Structures 3.11 3.12 Linear Data Structures

3.4.6 Disadvantages of Linked list 3.4.9 Complexity of Linked list


1. Time Complexity
➢ Memory usage - In linked list, node occupies more memory than array. Each
Operation Average Case Worst Case
node of the linked list occupies two types of variables, i.e., one is a simple
variable, and another one is the pointer variable. Insertion O(1) O(1)
➢ Traversal - Traversal is not easy in the linked list. If we have to access an element Deletion O(1) O(1)
in the linked list, we cannot access it randomly.
Search O(n) O(n)
➢ Reverse traversing - Backtracking or reverse traversing is difficult in a linked
list. In a doubly-linked list, it is easier but requires more memory to store the back 2. Space Complexity
pointer. Operation Space complexity
3.4.7 Applications of Linked list Insertion O(n)
➢ Using linked list, the polynomials can be represented as well as we can perform
Deletion O(n)
the operations on the polynomial.
➢ A linked list can be used to represent the sparse matrix. Search O(n)

➢ The various operations like student's details, employee's details, or product details
can be implemented using the linked list as the linked list uses the structure data 3.5 DOUBLY LINKED LIST
type that can hold different data types. ➢ Doubly linked list is a complex type of linked list
➢ Using linked list, we can implement stack, queue, tree, and other various data ➢ Here, a node contains a pointer to the previous as well as the next node in the
structures. sequence.
➢ If we want to represent the graph as an adjacency list, then it can be implemented ➢ Therefore, in a doubly-linked list, a node consists of three parts:
as a linked list.
 Node data,
➢ A linked list can be used to implement dynamic memory allocation. The dynamic
 Pointer to the next node in sequence (next pointer), and
memory allocation is the memory allocation done at the run-time.
 Pointer to the previous node (previous pointer).
3.4.8 Operations performed on Linked list
A sample node in a doubly linked list is shown in Fig. 3.5
➢ Insertion - This operation is performed to add an element into the list.
➢ Deletion - It is performed to delete an operation from the list.
➢ Display - It is performed to display the elements of the list.
➢ Search - It is performed to search an element from the list using the given key.

Fig. 3.5: Sample node in a doubly linked list


C Programming and Data Structures 3.13 3.14 Linear Data Structures
A doubly linked list containing three nodes having numbers from 1 to 3 in their to the list therefore the prev of the list contains null. The next node of the list
data part, is shown in Fig 3.6 resides at address 4 therefore the first node contains 4 in its next pointer.
➢ We can traverse the list in this way until we find any node containing null or -1 in
its next part.

Fig. 3.6: Doubly Linked List


In C, structure of a node in doubly linked list can be given as:
struct node
{
struct node *prev;
int data;
struct node *next;
}
➢ The prev part of the first node and the next part of the last node will always contain
null indicating end in each direction.
➢ In a singly linked list, we could traverse only in one direction, because each node
contains address of the next node and it doesn't have any record of its previous Fig. 3.7: Memory Representation of a doubly linked list
nodes. However, doubly linked list overcome this limitation of singly linked list.
3.5.2 Operations on doubly linked list
➢ Due to the fact that, each node of the list contains the address of its previous node,
we can find all the details about the previous node as well by using the previous Table 3.1 describes all the operations performed on Doubly Linked List
address stored inside the previous part of each node. Table 3.1: Operations on Doubly Linked List

3.5.1 Memory Representation of a doubly linked list Sl. No. Operation Description
➢ Memory Representation of a doubly linked list is shown in Fig. 3.7. Generally, 1. Insertion at beginning Adding the node into the linked list at beginning.
doubly linked list consumes more space for every node and therefore, causes more 2. Insertion at end Adding the node into the linked list to the end.
expansive basic operations such as insertion and deletion. However, we can easily
3. Insertion after Adding the node into the linked list after the
manipulate the elements of the list since the list maintains pointers in both the
specified node specified node.
directions (forward and backward).
➢ In Fig 3.7, the first element of the list that is i.e. 13 stored at address 1. The head 4. Deletion at beginning Removing the node from beginning of the list
pointer points to the starting address 1. Since this is the first element being added 5. Deletion at the end Removing the node from end of the list.
C Programming and Data Structures 3.15 3.16 Linear Data Structures

6. Deletion of the node Removing the node which is present just after the Step 2: SET NEW_NODE = ptr
having given data node containing the given data. Step 3: SET ptr = ptr -> NEXT
7. Searching Comparing each node data with the item to be Step 4: SET NEW_NODE -> DATA = VAL
searched and return the location of the item in the
Step 5: SET NEW_NODE -> PREV = NULL
list if the item found else return null
Step 6: SET NEW_NODE -> NEXT = START
8. Traversing Visiting each node of the list at least once in order
to perform some specific operation like searching, Step 7: SET head -> PREV = NEW_NODE
sorting, display, etc. Step 8: SET head = NEW_NODE
Step 9: EXIT
3.5.2.1 Insertion at beginning
➢ There are two scenarios of inserting any element into doubly linked list. Either the
list is empty or it contains at least one element.
The following steps to be performed for insert a node in doubly linked list at beginning.
➢ Allocate the space for the new node in the memory.
➢ Check whether the list is empty or not. The list is empty if the condition head ==
NULL holds.
➢ In that case, the node will be inserted as the only node of the list and therefore the
prev and the next pointer of the node will point to NULL and the head pointer will
point to this node. Fig. 3.8: Insertion into Doubly Linked List at the beginning
➢ In the second scenario, the condition head == NULL become false and the node
will be inserted in beginning. 3.5.2.2 Insertion at end
➢ The next pointer of the node will point to the existing head pointer of the node. ➢ To insert a node in doubly linked list at the end, make sure whether the list is
empty or it contains any element. Use the following steps in order to insert the
➢ The prev pointer of the existing head will point to the new node being inserted.
node in doubly linked list at the end.
➢ Since, the node being inserted is the first node of the list and therefore it must
➢ Allocate the memory for the new node. Make the pointer ptr point to the new node
contain NULL in its prev pointer.
being inserted.
➢ Hence assign null to its previous part and make the head point to this node.
➢ Check whether the list is empty or not. The list is empty if the condition head ==
Algorithm 3.1 NULL holds.
Step 1: IF ptr = NULL ➢ In that case, the node will be inserted as the only node of the list and therefore the
Write OVERFLOW prev and the next pointer of the node will point to NULL and the head pointer will
point to this node.
Go to Step 9
➢ In the second scenario, the condition head == NULL become false. The new node
[END OF IF] will be inserted as the last node of the list.
C Programming and Data Structures 3.17 3.18 Linear Data Structures
➢ For this reason, we have to traverse the whole list in order to reach the last node 3.5.2.3 Insertion after specified node
of the list. Initialize the pointer temp to head and traverse the list by using this
To insert a node after the specified node in the list, we need to skip the required
pointer.
number of nodes in order to reach the mentioned node and then make the pointer
➢ Make the next pointer of temp point to the new node being inserted i.e. ptr. adjustments as required.
➢ Make the previous pointer of the node ptr point to the existing last node of the list
The following steps are used for this purpose.
i.e. temp.
➢ Allocate the memory for the new node.
➢ Make the next pointer of the node ptr point to the null as it will be the new last
➢ Traverse the list by using the pointer temp to skip the required number of nodes
node of the list.
in order to reach the specified node.
Algorithm 3.2 ➢ The temp would point to the specified node at the end of the for loop. The new
Step 1: IF PTR = NULL node needs to be inserted after this node. Make the next pointer of ptr point to the
Write OVERFLOW next node of temp.
Go to Step 11 ➢ Make the prev of the new node ptr point to temp.
[END OF IF] ➢ Make the next pointer of temp point to the new node ptr.
Step 2: SET NEW_NODE = PTR ➢ Make the previous pointer of the next node of temp point to the new node.
Step 3: SET PTR = PTR -> NEXT Algorithm 3.3
Step 4: SET NEW_NODE -> DATA = VAL Step 1: IF PTR = NULL
Step 5: SET NEW_NODE -> NEXT = NULL Write OVERFLOW
Step 6: SET TEMP = START Go to Step 15
Step 7: Repeat Step 8 while TEMP -> NEXT != NULL [END OF IF]
Step 8: SET TEMP = TEMP -> NEXT Step 2: SET NEW_NODE = PTR
[END OF LOOP] Step 3: SET PTR = PTR -> NEXT
Step 9: SET TEMP -> NEXT = NEW_NODE Step 4: SET NEW_NODE -> DATA = VAL
Step 10C: SET NEW_NODE -> PREV = TEMP
Step 5: SET TEMP = START
Step 11: EXIT
Step 6: SET I = 0
Step 7: REPEAT 8 to 10 until I
Step 8: SET TEMP = TEMP -> NEXT
STEP 9: IF TEMP = NULL
STEP 10: WRITE "LESS THAN DESIRED NO. OF ELEMENTS"
GOTO STEP 15
Fig. 3.9: Insertion into Doubly Linked List at the end
C Programming and Data Structures 3.19 3.20 Linear Data Structures
[END OF IF]
[END OF LOOP]

Step 11: SET NEW_NODE -> NEXT = TEMP -> NEXT


Step 12: SET NEW_NODE -> PREV = TEMP
Step 13 : SET TEMP -> NEXT = NEW_NODE
Step 14: SET TEMP -> NEXT -> PREV = NEW_NODE
Step 15: EXIT

Fig. 3.11: Deletion in Doubly Linked List from beginning

3.5.2.5 Deletion at the end


Deletion of the last node in a doubly linked list needs traversing the list in order
to reach the last node of the list and then make pointer adjustments at that position. To
delete the last node of the list, following steps are performed.
➢ If the list is already empty then the condition head == NULL will become true
Fig. 3.10: Insertion of Doubly Linked List after specified node and therefore the operation cannot be carried on.
➢ If there is only one node in the list then the condition head → next == NULL
3.5.2.4 Deletion at beginning become true. In this case, we just need to assign the head of the list to NULL and
➢ Deletion in doubly linked list at the beginning is the simplest operation. free head in order to completely delete the list.
➢ Just need to copy the head pointer to pointer ptr and shift the head pointer to its ➢ Otherwise, just traverse the list to reach the last node of the list.
next. ➢ The ptr would point to the last node of the ist at the end of the for loop. Just make
➢ Make the prev of this new head node point to NULL. the next pointer of the previous node of ptr to NULL.
➢ Now free the pointer ptr by using the free function. ➢ Free the pointer as this the node which is to be deleted.
Algorithm 3.4 Algorithm 3.5:
STEP 1: IF HEAD = NULL Step 1: IF HEAD = NULL
WRITE UNDERFLOW Write UNDERFLOW
GOTO STEP 6 Go to Step 7
STEP 2: SET PTR = HEAD [END OF IF]
STEP 3: SET HEAD = HEAD → NEXT Step 2: SET TEMP = HEAD
STEP 4: SET HEAD → PREV = NULL Step 3: REPEAT STEP 4 WHILE TEMP->NEXT != NULL
STEP 5: FREE PTR Step 4: SET TEMP = TEMP->NEXT
STEP 6: EXIT
C Programming and Data Structures 3.21 3.22 Linear Data Structures
[END OF LOOP] Step 3: Repeat Step 4 while TEMP -> DATA != ITEM
Step 4: SET TEMP = TEMP -> NEXT
Step 5: SET TEMP ->PREV-> NEXT = NULL
[END OF LOOP]
Step 6: FREE TEMP
Step 5: SET PTR = TEMP -> NEXT
Step 7: EXIT
Step 6: SET TEMP -> NEXT = PTR -> NEXT
Step 7: SET PTR -> NEXT -> PREV = TEMP
Step 8: FREE PTR
Step 9: EXIT

Fig. 3.12: Deletion in Doubly Linked List at the end

3.5.2.6 Deletion of the node having given data Fig. 3.13: Deletion of a specified node in Doubly Linked List at the end
➢ Copy the head pointer into a temporary pointer temp.
3.5.2.7 Searching for a specific node
➢ Traverse the list until we find the desired data value.
To search for a specific element in the list, traverse the list in order. The
➢ Check if this is the last node of the list. If it is so then we can't perform deletion.
following operations to be performed in order to search a specific operation.
➢ Check if the node which is to be deleted, is the last node of the list, if it so then
➢ Copy head pointer into a temporary pointer variable ptr
we have to make the next pointer of this node point to null so that it can be the
➢ Traverse the list until the pointer ptr becomes null. Keep shifting pointer to its
new last node of the list.
next and increasing i by +1.
➢ Otherwise, make the pointer ptr point to the node which is to be deleted.
➢ Compare each element of the list with the item which is to be searched.
➢ Make the next of temp point to the next of ptr.
➢ If the item matched with any node value then the location of that value I will be
➢ Make the previous of next node of ptr point to temp. free the ptr.
returned from the function else NULL is returned.
Algorithm 3.6
Algorithm 3.7
Step 1: IF HEAD = NULL
Step 1: IF HEAD == NULL
Write UNDERFLOW
WRITE "UNDERFLOW"
Go to Step 9
GOTO STEP 8
[END OF IF]
[END OF IF]
Step 2: SET TEMP = HEAD
C Programming and Data Structures 3.23 3.24 Linear Data Structures
Step 2: Set PTR = HEAD ➢ As with a singly linked list, it is the easiest data structure to implement.
Step 3: Set i = 0 ➢ The traversal of this doubly linked list is bidirectional which is not possible in a
singly linked list.
Step 4: Repeat step 5 to 7 while PTR != NULL ➢ Deletion of nodes is easy as compared to a Singly Linked List.
Step 5: IF PTR → data = item 3.5.4 Disadvantages of Doubly Linked Lists
return i ➢ It uses extra memory when compared to the array and singly linked list.
[END OF IF] ➢ Since elements in memory are stored randomly, therefore the elements are
accessed sequentially no direct access is allowed.
Step 6: i = i + 1
Step 7: PTR = PTR → next 3.6 CIRCULAR LINKED LIST
Step 8: Exit ➢ In a circular singly linked list, the last node of the list contains a pointer to the first
node of the list.
3.5.2.8 Traversing in doubly linked list
➢ We can have circular singly linked list as well as circular doubly linked list.
Traversing is the most common operation in case of each data structure. For this purpose,
➢ We traverse a circular singly linked list until we reach the same node where we
➢ Copy the head pointer in any of the temporary pointer ptr. started.
➢ Traverse through the list by using while loop. ➢ The circular singly liked list has no beginning and no ending.
➢ Keep shifting value of pointer variable ptr until we find the last node. ➢ There is no null value present in the next part of any of the nodes.
➢ The last node contains null in its next part. ➢ Circular linked list are mostly used in task maintenance in operating systems. Fig.
Algorithm 3.8 3.14 shows a circular singly linked list.
Step 1: IF HEAD == NULL
WRITE "UNDERFLOW"
GOTO STEP 6
[END OF IF]
Step 2: Set PTR = HEAD
Step 3: Repeat step 4 and 5 while PTR != NULL
Step 4: Write PTR → data Fig. 3.14: Circular Singly Linked List.
Step 5: PTR = PTR → next 3.6.1 Memory Representation of circular linked list
Step 6: Exit ➢ Fig 3.15 shows the memory representation of a circular linked list containing
marks of a student in 4 subjects. However, the image shows a glimpse of how the
3.5.3 Advantages of Doubly Linked Lists circular list is being stored in the memory. The start or head of the list is pointing
➢ Reversing the doubly linked list is very easy. to the element with the index 1 and containing 13 marks in the data part and 4 in
➢ It can allocate or reallocate memory easily during its execution.
C Programming and Data Structures 3.25 3.26 Linear Data Structures
the next part. Which means that it is linked with the node that is being stored at Traversing Visiting each element of the list at least once in
5.
4th index of the list. order to perform some specific operation.
➢ However, due to the fact that we are considering circular linked list in the memory
therefore the last node of the list contains the address of the first node of the list. 3.6.2.1 Insertion at the beginning
➢ There are two scenario in which a node can be inserted in circular singly linked
list at beginning. Either the node will be inserted in an empty list or the node is to
be inserted in an already filled list.
➢ Firstly, allocate the memory space for the new node by using the malloc method
of C language.
➢ In the first scenario, the condition head == NULL will be true. Since, the list in
which, we are inserting the node is a circular singly linked list, therefore the only
node of the list (which is just inserted into the list) will point to itself only.
➢ Also need to make the head pointer point to this node.
➢ In the second scenario, the condition head == NULL will become false which
means that the list contains at least one node.
➢ In this case, traverse the list in order to reach the last node of the list.
➢ At the end of the loop, the pointer temp would point to the last node of the list.
➢ Make the next pointer of the last node point to the head node of the list and the
Fig. 3.15: Memory Representation of Circular Linked List new node which is being inserted into the list will be the new head node of the list
➢ Therefore the next pointer of temp will point to the new node ptr.
3.6.2 Operations on Circular Singly linked list
Algorithm 3.9
Table 3.2 describes all the operations performed on a Doubly Linked List
Step 1: IF PTR = NULL
Table 3.2: Operations on Doubly Linked List
Write OVERFLOW
Sl. No. Operation Description
Go to Step 11
Insertion at beginning Adding a node into circular singly linked list at
1. [END OF IF]
the beginning.
Insertion at end Adding a node into circular singly linked list at Step 2: SET NEW_NODE = PTR
2.
the end. Step 3: SET PTR = PTR -> NEXT
Deletion at beginning Removing the node from circular singly linked Step 4: SET NEW_NODE -> DATA = VAL
3.
list at the beginning. Step 5: SET TEMP = HEAD
Searching Compare each element of the node with the Step 6: Repeat Step 8 while TEMP -> NEXT != HEAD
4. given item and return the location at which the
Step 7: SET TEMP = TEMP -> NEXT
item is present in the list otherwise return null.
C Programming and Data Structures 3.27 3.28 Linear Data Structures
[END OF LOOP] Go to Step 1
[END OF IF]
Step 8: SET NEW_NODE -> NEXT = HEAD
Step 2: SET NEW_NODE = PTR
Step 9: SET TEMP → NEXT = NEW_NODE
Step 3: SET PTR = PTR -> NEXT
Step 10: SET HEAD = NEW_NODE
Step 11: EXIT Step 4: SET NEW_NODE -> DATA = VAL
Step 5: SET NEW_NODE -> NEXT = HEAD
Step 6: SET TEMP = HEAD
Step 7: Repeat Step 8 while TEMP -> NEXT != HEAD
Step 8: SET TEMP = TEMP -> NEXT
[END OF LOOP]
Step 9: SET TEMP -> NEXT = NEW_NODE
Step 10: EXIT

Fig. 3.16: Insertion into a Circular Linked List at the beginning

3.6.2.2 Insertion at the end


➢ Allocate the memory space for the new node by using the malloc method of C
language.
➢ In the first scenario, the condition head == NULL will be true.
➢ Also make the head pointer point to this node.
➢ In the second scenario, the condition head == NULL will become false which
means that the list contains at least one node. Fig. 3.17: Insertion into a Circular Linked List at the end
➢ In this case, traverse the list in order to reach the last node of the list. 3.6.2.3 Deletion at the beginning
➢ At the end of the loop, the pointer temp would point to the last node of the list. In order to delete a node in circular singly linked list, we need to make a few
➢ The existing last node i.e. temp must point to the new node ptr pointer adjustments. There are three scenarios of deleting a node from circular singly
Algorithm 3.10 linked list at beginning.
Step 1: IF PTR = NULL ➢ Scenario 1: (The list is Empty) - If the list is empty then the condition head ==
NULL will become true, in this case, just to print underflow on the screen and
Write OVERFLOW make exit.
C Programming and Data Structures 3.29 3.30 Linear Data Structures
➢ Scenario 2: (The list contains single node) - If the list contains single node then, 3.6.2.4 Deletion at the end
the condition head → next == head will become true. In this case, delete the entire ➢ Scenario 1 (the list is empty) - If the list is empty then the condition head ==
list and make the head pointer free. NULL will become true, in this case, just to print underflow on the screen and
➢ Scenario 3: (The list contains more than one node) - If the list contains more than make exit.
one node then, in that case, traverse the list by using the pointer ptr to reach the
➢ Scenario 2(the list contains single element) - If the list contains single node then,
last node of the list.
the condition head → next == head will become true. In this case, delete the entire
➢ At the end of the loop, the pointer ptr point to the last node of the list.
list and make the head pointer free.
➢ The last node of the list will point to the next of the head node.
➢ Scenario 3(the list contains more than one element) - If the list contains more than
➢ Now, free the head pointer by using the free() method.
one element, then in order to delete the last element, reach the last node. Also keep
➢ Make the node pointed by the next of the last node, the new head of the list.
track of the second last node of the list. For this purpose, the two pointers ptr and
Algorithm 3.11 preptr are defined.
Step 1: IF HEAD = NULL ➢ Make just one more pointer adjustment. We need to make the next pointer of
Write UNDERFLOW preptr point to the next of ptr (i.e. head) and then make pointer ptr free.
Go to Step 8 Algorithm 3.12
[END OF IF] Step 1: IF HEAD = NULL
Step 2: SET PTR = HEAD
Write UNDERFLOW
Step 3: Repeat Step 4 while PTR → NEXT != HEAD
Step 4: SET PTR = PTR → next Go to Step 8
[END OF LOOP] [END OF IF]
Step 5: SET PTR → NEXT = HEAD → NEXT Step 2: SET PTR = HEAD
Step 6: FREE HEAD
Step 3: Repeat Steps 4 and 5 while PTR -> NEXT != HEAD
Step 7: SET HEAD = PTR → NEXT
Step 4: SET PREPTR = PTR
Step 8: EXIT
Step 5: SET PTR = PTR -> NEXT
[END OF LOOP]
Step 6: SET PREPTR -> NEXT = HEAD
Step 7: FREE PTR
Step 8: EXIT

Fig. 3.18: Deletion in a Circular Linked List at beginning


C Programming and Data Structures 3.31 3.32 Linear Data Structures
End of IF
STEP 7: I = I + 1
STEP 8: PTR = PTR → NEXT
[END OF LOOP]
STEP 9: EXIT

3.6.2.5 Searching
➢ Traversing in circular singly linked list can be done through a loop.
➢ Initialize the temporary pointer variable temp to head pointer and run the while
loop until the next pointer of temp becomes head.
Fig. 3.19: Deletion in a Circular Linked List at the end
Algorithm 3.14
3.6.2.5 Searching
STEP 1: SET PTR = HEAD
➢ Searching in circular singly linked list needs traversing across the list.
STEP 2: IF PTR = NULL
➢ The item which is to be searched in the list is matched with each node data of the
list once. WRITE "EMPTY LIST"
➢ If the match found then the location of that item is returned otherwise -1 is GOTO STEP 8
returned. END OF IF
Algorithm 3.13 STEP 4: REPEAT STEP 5 AND 6 UNTIL PTR → NEXT != HEAD
STEP 1: SET PTR = HEAD STEP 5: PRINT PTR → DATA
STEP 2: Set I = 0 STEP 6: PTR = PTR → NEXT
STEP 3: IF PTR = NULL [END OF LOOP]
WRITE "EMPTY LIST" STEP 7: PRINT PTR→ DATA
GOTO STEP 8 STEP 8: EXIT
END OF IF 3.6.3 Advantages of Circular Linked Lists
STEP 4: IF HEAD → DATA = ITEM It is possible to traverse from the last node back to the first i.e. the head node.
WRITE i+1 RETURN [END OF IF] ➢ The starting node does not matter as we can traverse each and every node despite
STEP 5: REPEAT STEP 5 TO 7 UNTIL PTR->next != head whatever node we keep as the starting node.
STEP 6: if ptr → data = item ➢ The previous node can be easily identified.
write i+1 ➢ There is no need for a NULL function to code. The circular list never identifies a
NULL identifier unless it is fully assigned.
RETURN
➢ Circular linked lists are beneficial for end operations as start and finish coincide
C Programming and Data Structures 3.33 3.34 Linear Data Structures

3.6.4 Disadvantages of Circular Linked Lists the value entered first will be removed last. In the above case, the value 5 is
➢ If the circular linked list is not handled properly then it can lead to an infinite loop entered first, so it will be removed only after the deletion of all the other elements.
as it is circular in nature.
➢ In comparison with singly-linked lists, doubly linked lists are more complex in
nature
➢ Direct accessing of elements is not possible.
➢ It is generally a complex task to reverse a circular linked list

3.7 STACK ADT


➢ A Stack is a linear data structure that follows the LIFO (Last-In-First-Out)
principle.
➢ A Stack is an abstract data type with a pre-defined capacity, which means that it
can store the elements of a limited size. Fig. 3.20: Working principle of a Stack

➢ Stack has one end, whereas the Queue has two ends (front and rear). 3.7.2 Operations on Stack
➢ It contains only one pointer top pointer pointing to the topmost element of the The following are some common operations implemented on the stack:
stack. ➢ push(): When we insert an element in a stack then the operation is known as a
➢ Whenever an element is added in the stack, it is added on the top of the stack, and push. If the stack is full then the overflow condition occurs.
the element can be deleted only from the stack. ➢ pop(): When we delete an element from the stack, the operation is known as a pop.
➢ In other words, a stack can be defined as a container in which insertion and If the stack is empty means that no element exists in the stack, this state is known
deletion can be done from the one end known as the top of the stack. as an underflow state.
➢ isEmpty(): It determines whether the stack is empty or not.
3.7.1 Working of Stack
➢ isFull(): It determines whether the stack is full or not.'
➢ Stack works on the LIFO pattern. As we can observe in figure 3.20, there are five
memory blocks in the stack; therefore, the size of the stack is 5. ➢ peek(): It returns the element at the given position.
➢ Suppose we want to store the elements in a stack and let's assume that stack is ➢ count(): It returns the total number of elements available in a stack.
empty. We have taken the stack of size 5 as shown below in which we are pushing ➢ change(): It changes the element at the given position.
the elements one by one until the stack becomes full. ➢ display(): It prints all the elements available in the stack
➢ Since our stack is full as the size of the stack is 5. In the above cases, we can
3.7.2.1 PUSH operation
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. ➢ Before inserting an element in a stack, we check whether the stack is full.
➢ If we try to insert the element in a stack, and the stack is full, then the overflow
➢ When we perform the delete operation on the stack, there is only one way for entry
condition occurs.
and exit as the other end is closed. It follows the LIFO pattern, which means that
➢ When we initialize a stack, we set the value of top as -1 to check that the stack is
empty.
C Programming and Data Structures 3.35 3.36 Linear Data Structures
➢ When the new element is pushed in a stack, first, the value of the top gets
incremented, i.e., top=top+1, and the element will be placed at the new position
of the top.
➢ The elements will be inserted until we reach the max size of the stack.

Fig. 3.22 POP Operation in Stack

3.7.3 Applications of Stack


➢ Balancing of symbols: Stack is used for balancing a symbol.
➢ String reversal: Stack is also used for reversing a string
➢ UNDO/REDO: It can also be used for performing UNDO/REDO operations.
➢ Recursion: The recursion means that the function is calling itself again.
➢ DFS(Depth First Search): This search is implemented on a Graph, and Graph
uses the stack data structure.
➢ Backtracking: In order to come at the beginning of the path to create a new path,
use the stack data structure
Fig. 3.21 PUSH Operation in Stack ➢ Expression conversion: Stack can also be used for expression conversion.
3.7.2.2 POP operation  Infix to prefix
 Infix to postfix
➢ Before deleting the element from the stack, we check whether the stack is empty.
 Prefix to infix
➢ If we try to delete the element from the empty stack, then the underflow condition
occurs.  Prefix to postfix
➢ If the stack is not empty, we first access the element which is pointed by the top  Postfix to infix
➢ Once the pop operation is performed, the top is decremented by 1, i.e., top=top-1. ➢ Memory management: The stack manages the memory. The memory is assigned
in the contiguous memory blocks.

3.8 IMPLEMENTATION OF STACK


➢ Stack can be easily implemented using an Array or a Linked List. Arrays are
quick, but are limited in size and Linked List requires overhead to allocate, link,
unlink, and deallocate, but is not limited in size.
C Programming and Data Structures 3.37 3.38 Linear Data Structures

3.8.1 Array implementation of Stack }


}
➢ In array implementation, the stack is formed by using the array. All the operations
regarding the stack are performed using arrays. Let’s see how each operation can 3.8.1.2 Deletion of an element from a stack (Pop operation)
be implemented on the stack using array data structure. ➢ 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
3.8.1.1 Adding an element onto the stack (push operation)
from the stack.
➢ Adding an element into the top of the stack is referred to as push operation. Push
➢ The top most element of the stack is stored in another variable and then the top is
operation involves following two steps.
decremented by 1.
1. Increment the variable Top so that it can now refere to the next memory ➢ The operation returns the deleted value that was stored in another variable as the
location. result.
2. Add element at the position of incremented top. This is referred to as adding ➢ The underflow condition occurs when we try to delete an element from an already
new element at the top of the stack. empty stack.
➢ Stack is overflown when we try to insert an element into a completely filled stack
Algorithm 3.16
therefore, our main function must always avoid stack overflow condition.
begin
Algorithm 3.15
if top = 0 then stack empty;
begin
item := stack(top);
if top = n then stack full
top = top - 1;
top = top + 1
end;
stack (top) : = item;
Time Complexity: O (1)
end
Time Complexity: O (1) 3.8.1.2.1 Implementation of POP algorithm using C language
int pop ()
3.8.1.1.1 Implementation of push algorithm in C language
{
void push (int val,int n) //n is size of the stack
if(top == -1)
{
{
if (top == n )
printf("Underflow");
printf("\n Overflow");
return 0;
else
}
{
else
top = top +1;
{
stack[top] = val;
C Programming and Data Structures 3.39 3.40 Linear Data Structures
return stack[top - - ]; 3.8.2 Linked list implementation of stack
} ➢ Linked list allocates the memory dynamically. However, time complexity in both
} the scenario is same for all the operations i.e. push, pop and peek.
➢ In linked list implementation of stack, the nodes are maintained non-contiguously
in the memory.
3.8.1.3 Visiting each element of the stack (Peek operation)
➢ Each node contains a pointer to its immediate successor node in the stack.
➢ Peek operation involves returning the element which is present at the top of the
➢ Stack is said to be overflown if the space left in the memory heap is not enough
stack without deleting it.
to create a node.
➢ Underflow condition can occur if we try to return the top element in an already
➢ The top most node in the stack always contains null in its address field.
empty stack.
Algorithm 3.17
PEEK (STACK, TOP)
Begin
if top = -1 then stack empty
item = stack[top]
return item
End
Time complexity: O(n)
Implementation of Peek algorithm in C language
int peek()
{ Fig. 3.23: Linked List implementation of Stack

if (top == -1) 3.8.2.1 Adding a node to the stack (Push operation)


{ ➢ 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
printf("Underflow"); implementation. In order to push an element onto the stack, the following steps
return 0; are involved.
}  Create a node first and allocate memory to it.
else  If the list is empty 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
return stack [top]; the address part of the node.

}
}
C Programming and Data Structures 3.41 3.42 Linear Data Structures

 If there are some nodes in the list already, then add the new element in the if(head==NULL)
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. ptr->val = val;

Time Complexity: O (1) ptr -> next = NULL;


head=ptr;
}
else
{
ptr->val = val;
ptr->next = head;
head=ptr;
}
printf("Item pushed");
}
Fig 3.24 Adding new Node to Stack
}
3.8.2.1.1 Implementation of PUSH in C Language Program
void push () 3.8.2.2 Deleting a node from the stack (POP operation)
➢ Deleting a node from the top of stack is referred to as pop operation. Deleting a
{
node from the linked list implementation of stack is different from that in the array
int val; implementation.
struct node *ptr =(struct node*)malloc(sizeof(struct node)); ➢ In order to pop an element from the stack, do the following steps:
if(ptr == NULL)  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 head
printf("not able to push the element"); pointer of the list points to null.

}  Adjust the head pointer accordingly: In stack, the elements are popped only
from one end, therefore, the value stored in the head pointer must be deleted
else
and the node must be freed. The next node of the head node now becomes the
{ head node.
printf("Enter the value"); Time Complexity: O (n)
scanf("%d",&val);
C Programming and Data Structures 3.43 3.44 Linear Data Structures

3.8.2.2.1 Implementation of POP in C Language Program struct node *ptr;


void pop() ptr=head;
{ if(ptr == NULL)
int item; {
struct node *ptr;
printf("Stack is empty\n");
if (head == NULL)
}
{
printf("Underflow"); else

} {
else printf("Printing Stack elements \n");
{ while(ptr!=NULL)
item = head->val; {
ptr = head;
printf("%d\n",ptr->val);
head = head->next;
ptr = ptr->next;
free(ptr);
}
printf("Item popped");
} }

} }

3.8.2.3 Display the nodes (Traversing) 3.9 APPLICATIONS OF STACK


Displaying all the nodes of a stack needs traversing all the nodes of the linked list ➢ A Stack is a widely used linear data structure in modern computers in which
organized in the form of stack. For this do the following steps. insertions and deletions of an element can occur only at one end, i.e., top of the
➢ Copy the head pointer into a temporary pointer. Stack. It is used in all those applications in which data must be stored and retrieved
➢ Move the temporary pointer through all the nodes of the list and print the value in the last.
field attached to every node. ➢ Following are the various Applications of Stack in Data Structure:
Time Complexity: O (n)  Evaluation of Arithmetic Expressions
 Balancing Symbols
3.8.2.3.1 Implementation of Display in C Language Program
 Processing Function Calls
void display()
{  Backtracking

int i;  Reverse a Data


C Programming and Data Structures 3.45 3.46 Linear Data Structures

3.9.1 Evaluation of Arithmetic Expressions Example 3.4: A + B, (C - D) etc.


➢ A stack is a very effective data structure for evaluating arithmetic expressions in All these expressions are in infix notation because the operator comes between
programming languages. An arithmetic expression consists of operands and the operands.
operators.
3.9.1.2 Prefix Notation
➢ In addition to operands and operators, the arithmetic expression may also include
parenthesis like "left parenthesis" and "right parenthesis". The prefix notation places the operator before the operands. This notation was
introduced by the Polish mathematician and hence often referred to as polish notation.
Example 3.3: A + (B - C)
Example 3.5: + A B, -CD etc.
To evaluate the expressions, one needs to be aware of the standard precedence
All these expressions are in prefix notation because the operator comes before the
rules for arithmetic expression. The precedence rules for the five basic arithmetic
operands.
operators are:
Operators Associativity Precedence 3.9.1.3 Postfix Notation
The postfix notation places the operator after the operands. This notation is just
^ exponentiation Right to left Highest followed by
the reverse of Polish notation and also known as Reverse Polish notation.
*Multiplication and /division
Example 3.6: AB +, CD+, etc.
*Multiplication, Left to right Highest followed by + addition
/division and - subtraction All these expressions are in postfix notation because the operator comes after the
operands.
+ addition, - Left to right lowest
Table 3.3 illustrates the conversion of Arithmetic Expression into various Notations
subtraction
Table 3.3: Conversion of Arithmetic Expression into various Notations

Evaluation of Arithmetic Expression requires two steps: Infix Notation Prefix Notation Postfix Notation
➢ First, convert the given expression into special notation. A*B *AB AB*
➢ Evaluate the expression in this new notation. (A+B)/C /+ ABC AB+C/
Notations for Arithmetic Expression (A*B) + (D-C) +*AB - DC AB*DC-+
There are three notations to represent an arithmetic expression:
➢ Infix Notation Let's take the example of Converting an infix expression into a postfix expression
➢ Prefix Notation
➢ Postfix Notation

3.9.1.1 Infix Notation


The infix notation is a convenient way of writing an expression in which each
operator is placed between the operands. Infix expressions can be parenthesized or un
parenthesized depending upon the problem requirement.
C Programming and Data Structures 3.47 3.48 Linear Data Structures
➢ When an operator encounters the scanning process, the Stack must contain a pair
of operands or intermediate results previously calculated.
➢ When an expression has been completely evaluated, the Stack must contain
exactly one value.
Example 3.7
Now let us consider the following infix expression 2 * (4+3) - 5.
Its equivalent postfix expression is 2 4 3 + * 5.
The following step illustrates how this postfix expression is evaluated.

3.9.2 Balancing Symbols


In the above example, the only change from the postfix expression is that the
➢ Stacks can be used to check if the given expression has balanced symbols or not.
operator is placed before the operands rather than between the operands.
➢ The algorithm is very much useful in compilers.
Evaluating Postfix expression ➢ Each time parser reads one character at a time.
➢ Stack is the ideal data structure to evaluate the postfix expression because the top
➢ If the character is an opening delimiter like ‘(‘ , ‘{‘ or ‘[‘ then it is PUSHED in to
element is always the most recent operand. The next element on the Stack is the the stack.
second most recent operand to be operated on.
➢ When a closing delimiter is encountered like ‘)’ , ‘}’ or ‘]’ is encountered, the
➢ Before evaluating the postfix expression, the following conditions must be stack is popped.
checked. If any one of the conditions fails, the postfix expression is invalid.
C Programming and Data Structures 3.49 3.50 Linear Data Structures
➢ The opening and closing delimiter are then compared. ( Push ( ((
➢ If they match, the parsing of the string continues. ) Pop ( (
➢ If they do not match, the parser indicates that there is an error on the line.
Test if ( and A[i] match? YES
A linear time O(n) algorithm based on stack can be given as:-
[ Push [ ([
Create a stack.
( Push ( ([(
while ( end of input is not reached ) {
) Pop ) )
If the character read is not a symbol to be balanced, ignore it.
Test if ( and A[i] match? YES
If the character is an opening delimiter like ( , { or [ , PUSH it into the stack.
] Pop [ (
If it is a closing symbol like ) , } , ] , then if the stack is empty report an error,
Test if [ and A[i] match? YES
otherwise POP the stack.
) Pop (
If the symbol POP-ed is not the corresponding delimiter, report an error.
Test if ( and A[i] match? YES
At the end of the input, if the stack is not empty report an error.
Example 3.8 Test if Stack is Empty? YES TRUE

EXAMPLE Valid? Description


3.9.3 Processing Function Calls
(A+B) + (C-D) Yes The expression is having balanced
➢ Stack plays an important role in programs that call several functions in succession.
symbol
Suppose we have a program containing three functions: A, B, and C. function A
((A+B) + (C-D) No One closing brace is missing. invokes function B, which invokes the function C.
((A+B) + [C-D]) Yes Opening and closing braces correspond
((A+B) + [C-D]] No The last brace does not correspond with
the first opening brace.
(A+B) + (C-D) Yes The expression is having balanced
symbol

For tracing the algorithm let us assume that the input is () (() [()])
Fig. 3.24: Invoking Function Calls
Input Symbol Operation Stack Output ➢ When we invoke function A, which contains a call to function B, then its
( Push ( ( processing will not be completed until function B has completed its execution and
) Pop ( returned. Similarly for function B and C. So we observe that function A will only
be completed after function B is completed and function B will only be completed
Test if ( and A[i] match? YES
after function C is completed.
( Push ( (
C Programming and Data Structures 3.51 3.52 Linear Data Structures
➢ Therefore, function A is first to be started and last to be completed. To conclude,  If one can successfully place a queen in the last row, then a solution is found.
the above function activity matches the last in first out behavior and can easily be Now backtrack to find the next solution
handled using Stack.
➢ We can use a stack to indicate the positions of the queens. Importantly, notice that
➢ Consider addrA, addrB, addrC be the addresses of the statements to which control we only have to put the column positions of the queens on the stack. We can
is returned after completing the function A, B, and C, respectively. determine each queen's coordinates given only the stack. We simply combine the
position of an element in the stack (the row) with the value of that element (the
column) for each queen.
➢ Two examples of this are shown below:

Fig. 3.25: Different states of stack


➢ Figure 3.26 shows that return addresses appear in the Stack in the reverse order in ➢ Starting with a queen in the first row, first column (represented by a stack
which the functions were called. After each function is completed, the pop containing just "0"), we search left to right for a valid position to place another
operation is performed, and execution continues at the address removed from the queen in the next available row.
Stack. ➢ If we find a valid position in this row, we push this position (i.e., the column
➢ Thus the program that calls several functions in succession can be handled number) to the stack and start again on the next row.
optimally by the stack data structure. Control returns to each function at a correct ➢ If we don't find a valid position in this row, we backtrack to the previous row --
place, which is the reverse order of the calling sequence. that is to say, we pop the col position for the previous row from the stack and
3.9.4 Backtracking search for a valid position further down the row.
➢ Backtracking is used in algorithms in which there are steps along some path (state) ➢ Note, when the stack size gets to n, we will have placed n queens on the board,
from some starting point to some goal. It uses recursive calling to find the solution and therefore have a solution.
by building a solution step by step increasing values with time. It removes the ➢ Of course, there is nothing that requires there be only one solution. To find the
solutions that doesn't give rise to the solution of the problem based on the rest, every time a solution is found, we can pretend it is not a solution, backtrack
constraints given to solve the problem. to the previous row, and proceed to find the next solution.
➢ Let’s see how Stack is used in Backtracking in the N-Queens Problem ➢ Ultimately, every position in the first row will be considered. When there are not
➢ For the N-Queens problem, one way we can do this is given by the following: more valid positions in the first row and we need to backtrack, that's our cue that
 For each row, place a queen in the first valid position (column), and then move there are no more solutions to be found. Thus, we may stop searching when we
to the next row try to pop from the stack, but can't as it is empty.

 If there is no valid position, then one backtracks to the previous row and try ➢ Putting all this into pseudo-code form, we have the following algorithm...
the next position
C Programming and Data Structures 3.53 3.54 Linear Data Structures
Create empty stack and set current position to 0 character of the String is on the Top of the Stack and after performing the pop
Repeat { operation in the Stack, the Stack returns the String in Reverse order.

loop from current position to the last position until valid position found //current
row
if there is a valid position {
push the position to stack, set current position to 0 // move to next row
}
if there is no valid position {
if stack is empty, break // stop search
else pop stack, set current position to next position // backtrack to previous Fig. 3.26: Reverse a String using Stack
row
3.9.5.2 Converting Decimal to Binary
}
➢ Although decimal numbers are used in most business applications, some scientific
if stack has size N { // a solution is found and technical applications require numbers in either binary, octal, or hexadecimal.
pop stack, set current position to next position // backtrack to find next solution A stack can be used to convert a number from decimal to
} binary/octal/hexadecimal form.
} ➢ For converting any decimal number to a binary number, we repeatedly divide the
decimal number by two and push the remainder of each division onto the Stack
3.9.5 Reverse a Data until the number is reduced to 0. Then we pop the whole Stack and the result
➢ To reverse a given set of data, we need to reorder the data so that the first and last obtained is the binary equivalent of the given decimal number.
elements are exchanged, the second and second last element are exchanged, and
Example: 3.9:
so on for all other elements. For example, suppose we have a string “welcome”,
then on reversing it would be “emoclew”. Converting 14 number Decimal to Binary:
➢ There are different reversing applications:
 Reversing a string
 Converting Decimal to Binary

3.9.5.1 Reverse a String


➢ A Stack can be used to reverse the characters of a string. This can be achieved by
simply pushing one by one each character onto the Stack, which later can be
popped from the Stack one by one. Because of the last in first out property of the
Stack, the first character of the Stack is on the bottom of the Stack and the last
C Programming and Data Structures 3.55 3.56 Linear Data Structures
➢ In the above example, on dividing 14 by 2, we get seven as a quotient and one as ➢ Queues are used as buffers in most of the applications like MP3 media player, CD
the reminder, which is pushed on the Stack. On again dividing seven by 2, we get player, etc.
three as quotient and 1 as the reminder, which is again pushed onto the Stack. This ➢ Queue are used to maintain the play list in media players in order to add and
process continues until the given number is not reduced to 0. When we pop off remove the songs from the play-list.
the Stack completely, we get the equivalent binary number 1110. ➢ Queues are used in operating systems for handling interrupts.

3.10 QUEUE ADT 3.10.2 Basic Operations in Queue


➢ A queue can be defined as an ordered list which enables insert operations to be ➢ Enqueue operation: The term "enqueue" refers to the act of adding a new element
performed at one end called REAR and delete operations to be performed at to a queue.
another end called FRONT. ➢ Dequeue operation: Dequeue is the process of deleting an item from a queue. We
➢ Queue is an abstract data structure, somewhat similar to Stacks. Unlike stacks, a must delete the queue member that was put first since the queue follows the FIFO
queue is open at both its ends. One end is always used to insert data (enqueue) and principle. Front Operation: This works similarly to the peek operation in stacks
the other is used to remove data (dequeue) in that it returns the value of the first element without deleting it.
➢ Queue is referred to be as First In First Out list. i.e., the data item stored first will ➢ isEmpty Operation: The isEmpty() function is used to check if the Queue is empty
be accessed first. or not.
➢ For example, people waiting in line for a rail ticket form a queue. ➢ isFull Operation: The isFull() function is used to check if the Queue is full or not.

3.10.3 Types of Queue


➢ Simple Queue or Linear Queue
➢ Circular Queue
➢ Priority Queue
➢ Double Ended Queue (or Deque)

3.10.3.1 Simple Queue or Linear Queue


➢ In Linear Queue, an insertion takes place from one end while the deletion occurs
Fig. 3.27: Data Structure of Queue
from another end. The end at which the insertion takes place is known as the rear
3.10.1 Applications of Queue end, and the end at which the deletion takes place is known as front end. It strictly
Due to the fact that queue performs actions on first in first out basis which is quite follows the FIFO rule.
fair for the ordering of actions. There are various applications of queues discussed as ➢ The major drawback of using a linear Queue is that insertion is done only from
below. the rear end. If the first three elements are deleted from the Queue, we cannot
➢ Queues are widely used as waiting lists for a single shared resource like printer, insert more elements even though the space is available in a Linear Queue. In this
disk, CPU. case, the linear Queue shows the overflow condition as the rear is pointing to the
➢ Queues are used in asynchronous transfer of data (where data is not being last element of the Queue
transferred at the same rate between two processes) for eg. pipes, file IO, sockets.
C Programming and Data Structures 3.57 3.58 Linear Data Structures
There are two types of priority queue
1. Ascending priority queue - In ascending priority queue, elements can be inserted
in arbitrary order, but only smallest can be deleted first.
Fig. 3.28 Representation of Linear Queue
2. Descending priority queue - In descending priority queue, elements can be
3.10.3.2 Circular Queue inserted in arbitrary order, but only the largest element can be deleted first.
➢ In Circular Queue, all the nodes are represented as circular. It is similar to the 3.10.3.4 Deque (or, Double Ended Queue)
linear Queue except that the last element of the queue is connected to the first
➢ In Deque or Double Ended Queue, insertion and deletion can be done from both
element. It is also known as Ring Buffer, as all the ends are connected to another
ends of the queue either from the front or rear. It means that we can insert and
end.
delete elements from both front and rear ends of the queue. Deque can be used as
➢ The drawback that occurs in a linear queue is overcome by using the circular a palindrome checker means that if we read the string from both ends, then the
queue. If the empty space is available in a circular queue, the new element can be string would be the same.
added in an empty space by simply incrementing the value of rear. The main
➢ Deque can be used both as stack and queue as it allows the insertion and deletion
advantage of using the circular queue is better memory utilization.
operations on both ends.

Fig. 3.29 Representation of circular Queue

3.10.3.3 Priority Queue Fig. 3.31 Representation of Double Ended Queue


➢ It is a special type of queue in which the elements are arranged based on the
There are two types of Deque
priority. It is a special type of queue data structure in which every element has a
➢ Input restricted Deque - As the name implies, in input restricted queue, insertion
priority associated with it. Suppose some elements occur with the same priority,
operation can be performed at only one end, while deletion can be performed from
they will be arranged according to the FIFO principle.
both ends.
➢ Insertion in priority queue takes place based on the arrival, while deletion in the
➢ Output restricted Deque - As the name implies, in output restricted queue,
priority queue occurs based on the priority. Priority queue is mainly used to
deletion operation can be performed at only one end, while insertion can be
implement the CPU scheduling algorithms.
performed from both ends.

3.11 PRIORITY QUEUES


➢ 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
Fig. 3.30 Representation of Priority Queue priority queue.
C Programming and Data Structures 3.59 3.60 Linear Data Structures
➢ The priority queue supports only comparable elements, which means that the 3.11.2 Types of Priority Queue
elements are either arranged in an ascending or descending order.
There are two types of priority queue:
➢ For example, suppose we have some values like 1, 3, 4, 8, 14, 22 inserted in a
Ascending order priority queue
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 In ascending order priority queue, a lower priority number is given as a higher
having the lowest priority. 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
3.11.1 Characteristics of a Priority queue highest priority in a priority queue.
A priority queue is an extension of a queue that contains the following characteristics:
➢ 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.
Let's understand the priority queue through an example. Fig. 3.32 Ascending order priority queue
We have a priority queue that contains the following values: Descending order priority queue:
1, 3, 4, 8, 14, 22 In descending order priority queue, a higher priority number is given as a higher
All the values are arranged in ascending order. Now, we will observe how the priority in a priority. For example, we take the numbers from 1 to 5 arranged in
priority queue will look after performing the following operations: 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.
poll(): 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.
add(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.
poll(): It will remove '2' element from the priority queue as it has the highest priority
queue.
add(5): It will insert 5 element after 4 as 5 is larger than 4 and lesser than 8, so it will Fig. 3.33 Descending order priority queue
obtain the third highest priority in a priority queue. 3.11.3 Representation of priority queue
Now, let’s see how to represent the priority queue through a one-way list.
We will create the priority queue by using the list given below in which INFO list
contains the data elements, PRN list contains the priority numbers of each data element
available in the INFO list, and LINK basically contains the address of the next node.
C Programming and Data Structures 3.61 3.62 Linear Data Structures
priority queue using a heap data structure in this topic. Now, first we understand
the reason why heap is the most efficient way among all the other data structures.

3.11.5 Analysis of complexities using different implementations


➢ A comparative analysis of different implementations of priority queue is given in
table 3.4
Table 3.4 Analysis of priority queue
Operations peek insert delete
Linked List O(1) O(n) O(1)
Let's create the priority queue step by step. Binary Heap O(1) O(log n) O(log n)
In the case of priority queue, lower priority number is considered the higher Binary Search Tree O(1) O(log n) O(log n)
priority, i.e., lower priority number = higher priority.
Step 1: In the list, lower priority number is 1, whose data value is 333, so it will be inserted 3.11.6 Heap
in the list as shown in the below diagram: ➢ A heap is a tree-based data structure that forms a complete binary tree, and
Step 2: After inserting 333, priority number 2 is having a higher priority, and data values satisfies the heap property.
associated with this priority are 222 and 111. So, this data will be inserted based ➢ If A is a parent node of B, then A is ordered with respect to the node B for all
on the FIFO principle; therefore 222 will be added first and then 111. nodes A and B in a heap.
Step 3: After inserting the elements of priority 2, the next higher priority number is 4 and ➢ It means that the value of the parent node could be more than or equal to the value
of the child node, or the value of the parent node could be less than or equal to the
data elements associated with 4 priority numbers are 444, 555, 777. In this case,
value of the child node.
elements would be inserted based on the FIFO principle; therefore, 444 will be
added first, then 555, and then 777. ➢ Therefore, we can say that there are two types of heaps:
Step 4: After inserting the elements of priority 4, the next higher priority number is 5, and
the value associated with priority 5 is 666, so it will be inserted at the end of the
queue.

3.11.4 Implementation of Priority Queue Fig. 3.34 Max heap Fig. 3.35 Min heap
➢ The priority queue can be implemented in four ways that include arrays, linked  Max heap: The max heap is a heap in which the value of the parent node is
list, heap data structure and binary search tree. The heap data structure is the most greater than the value of the child nodes.
efficient way of implementing the priority queue, so we will implement the
C Programming and Data Structures 3.63 3.64 Linear Data Structures

 Min heap: The min heap is a heap in which the value of the parent node is
less than the value of the child nodes.

3.11.7 Priority Queue Operations


The common operations that we can perform on a priority queue are
➢ Insertion,
➢ Deletion and
➢ Peek
Let's see how we can maintain the heap data structure.

3.11.7.1 Inserting the element in a priority queue (max heap) Now, let’s try to insert a new element, 6. Since there are nodes present in the heap, we
If we insert an element in a priority queue, it will move to the empty slot by insert this node at the end of heap so it looks like this:
looking from top to bottom and left to right.
If the element is not in a correct place then it is compared with the parent node; if
it is found out of order, elements are swapped. This process continues until the element
is placed in a correct position.

Algorithm 3.18
START
If(no node):
Create node
Else:
Then, heapify operation is implemented. After which, the heap will look like this:
Insert node at end of heap
Heapify
END
Let us now see with an example how this works:
Example 3.10
Let’s say the elements are 1,4,2,7,8,5. The max-heap of these elements would look like:
C Programming and Data Structures 3.65 3.66 Linear Data Structures

3.11.7.2 Removing the minimum element from the priority queue


In a max heap, the maximum element is the root node. When we remove the root
node, it creates an empty slot. The last inserted element will be added in this empty slot.
Then, this element is compared with the child nodes, i.e., left-child and right child, and
swap with the smaller of the two. It keeps moving down the tree until the heap property
is restored.
Algorithm 3.19:
START
If node that needs to be deleted is a leaf node: Then, we remove the leaf node so it looks like this:
Remove the node
Else:
Swap node that needs to be deleted with the last leaf node present.
Remove the node
Heapify
END
Let us now see with an example how this works:
Example: 3.11
Then, heapify operation is implemented. After which, the heap will look like this:
Let’s say the elements are 1,4,2,7,8,5,6. The max-heap of these elements would look like:

3.11.7.3 Peeking the element from a priority queue


This will return the maximum element if a max-heap is used and the minimum
Now, let’s try to delete an element, 6. Since this is not a leaf node, we swap it with the number if a min-heap is used. To do both of these, we return root node. This is because
last leaf node so it looks like this: in the max-heap or the min-heap the maximum or minimum element will be present at
the root node respectively.
C Programming and Data Structures 3.67 3.68 Linear Data Structures

3.11.8 Applications of Priority Queue figure, the queue will look something like following. The value of rear will become 5
while the value of front remains same.
The following are the applications of a Priority Queue:
➢ It is used in Djikstra’s Algorithm – To find the shortest path between nodes in a
graph.
➢ It is used in Prim’s Algorithm – To find the Minimum Spanning Tree in a
weighted undirected graph.
➢ It is used in Heap Sort – To sort the Heap Data Structure
➢ It is used in Huffman Coding – A Data Compression Algorithm
➢ It is used in Operating Systems for:
Fig. 3.36: Array representation of Queue
o Priority Scheduling – Where processes must be scheduled according to their
priority.
o Load Balancing – Where network or application traffic must be balanced
across multiple servers.
o Interrupt Handling – When a current process is interrupted, a handler is
assigned to the same to rectify the situation immediately.
➢ A* Search Algorithm – A graph traversal and a path search algorithm

3.12 QUEUE IMPLEMENTATION Fig. 3.37: Queue after inserting an element


3.12.1 Array implementation of Queue After deleting an element, the value of front will increase from -1 to 0. However,
➢ Queue can be represented easily by using linear arrays. the queue will look something like following.
➢ 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 figure 3.36.
Fig. 3.38: Queue after deleting an element
The above figure 3.36 shows the queue of characters forming the English word
"HELLO". Since, No deletion is performed in the queue till now, therefore the value of 3.12.1.1 Algorithm to insert any element in a queue
front remains -1. However, the value of rear increases by one every time an insertion is ➢ Check if the queue is already full by comparing rear to max - 1. if so, then return
performed in the queue. After inserting an element into the queue shown in the above an overflow error.
C Programming and Data Structures 3.69 3.70 Linear Data Structures
➢ 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.
else
➢ Otherwise keep increasing the value of rear and insert each element one by one
{
having rear as the index.
rear = rear + 1;
Algorithm 3.20
}
Step 1: IF REAR = MAX - 1
queue[rear]=item;
Write OVERFLOW
}
Go to step
}
[END OF IF]
Step 2: IF FRONT = -1 and REAR = -1 3.12.1.3 Algorithm to delete an element from the queue
➢ If, the value of front is -1 or value of front is greater than rear, write an underflow
SET FRONT = REAR = 0
message and exit.
ELSE
➢ Otherwise, keep increasing the value of front and return the item stored at the front
SET REAR = REAR + 1 end of the queue at each time.
[END OF IF]
Algorithm 3.21
Step 3: Set QUEUE[REAR] = NUM
Step 1: IF FRONT = -1 or FRONT > REAR
Step 4: EXIT
Write UNDERFLOW
3.12.1.2 Implementation using C Function: ELSE
void insert (int queue[], int max, int front, int rear, int item) SET VAL = QUEUE[FRONT]
{ SET FRONT = FRONT + 1
if (rear + 1 == max) [END OF IF]
{ Step 2: EXIT
printf("overflow");
3.12.1.4 Implementation using C Function
}
int delete (int queue[], int max, int front, int rear)
else
{
{
int y;
if(front == -1 && rear == -1)
if (front == -1 || front > rear)
{
{
front = 0;
printf("underflow");
rear = 0;
C Programming and Data Structures 3.71 3.72 Linear Data Structures
} ➢ Each element of the queue points to its immediate next element in the memory.
else ➢ In the linked queue, there are two pointers maintained in the memory i.e. front
pointer and rear pointer.
{
➢ The front pointer contains the address of the starting element of the queue while
the rear pointer contains the address of the last element of the queue.
y = queue[front];
➢ Insertion and deletions are performed at rear and front end respectively.
if(front == rear)
➢ If front and rear both are NULL, it indicates that the queue is empty.
{
The linked representation of queue is shown in the figure 3.39
front = rear = -1;
else
front = front + 1;
}
Fig. 3.39 Linked list representation of queue
return y;
} 3.12.2.1 Insertion on Linked Queue
➢ The insert operation append the queue by adding an element to the end of the
}
queue.
3.12.1.5 Drawback of array implementation ➢ The new element will be the last element of the queue.
➢ Memory wastage: The space of the array, which is used to store queue elements, ➢ There can be the two scenario of inserting this new node ptr into the linked queue.
can never be reused to store the elements of that queue because the elements can ➢ In the first scenario, we insert element into an empty queue. In this case, the
only be inserted at front end and the value of front might be so high so that, all the condition front = NULL becomes true. Now, the new element will be added as the
space before that, can never be filled. only element of the queue and the next pointer of front and rear pointer both, will
➢ Deciding the array size: On of the most common problem with array point to NULL.
implementation is the size of the array which requires to be declared in advance. ➢ In the second case, the queue contains more than one element. The condition front
Due to the fact that, the queue can be extended at runtime depending upon the = NULL becomes false. In this scenario, we need to update the end pointer rear
problem, the extension in the array size is a time taking process and almost so that the next pointer of rear will point to the new node ptr.
impossible to be performed at runtime since a lot of reallocations take place.
➢ Since, this is a linked queue, hence we also need to make the rear pointer point to
3.12.2 Linked List implementation of Queue the newly added node ptr.
➢ One of the alternative of array implementation is linked list implementation of ➢ Also make the next pointer of rear point to NULL.
queue. Algorithm 3.22
➢ The storage requirement of linked representation of a queue with n elements is Step 1: Allocate the space for the new node PTR
O(n) while the time requirement for operations is O(1).
Step 2: SET PTR -> DATA = VAL
➢ In a linked queue, each node of the queue consists of two parts i.e. data part and
the link part.
C Programming and Data Structures 3.73 3.74 Linear Data Structures
Step 3: IF FRONT = NULL else
SET FRONT = REAR = PTR {
rear -> next = ptr;
SET FRONT -> NEXT = REAR -> NEXT = NULL
rear = ptr;
ELSE
rear->next = NULL;
SET REAR -> NEXT = PTR
}
SET REAR = PTR
}
SET REAR -> NEXT = NULL
}
[END OF IF]
Step 4: END 3.13 APPLICATIONS OF QUEUE
There are several algorithms that use queues to give efficient running times. Some
3.12.2.2 Implementation using C Function simple examples of queue usage are follows.
void insert(struct node *ptr, int item; )
3.13.1 Type declarations for queue-array implementation
{
struct queue_record
ptr = (struct node *) malloc (sizeof(struct node));
{
if(ptr == NULL)
unsigned int q_max_size; /* Maximum # of elements */
{
/* until Q is full */
printf("\nOVERFLOW\n");
unsigned int q_front;
return;
unsigned int q_rear;
}
unsigned int q_size; /* Current # of elements in Q */
else
element_type *q_array;
{
};
ptr -> data = item;
typedef struct queue_record * QUEUE
if(front == NULL)
{ 3.13.2 Routine to test whether a queue is empty-array implementation
front = ptr; int
rear = ptr; is_empty( QUEUE Q )

front -> next = NULL; {

rear -> next = NULL; return( Q->q_size == 0 );

} }
C Programming and Data Structures 3.75 3.76 Linear Data Structures

3.13.3 Routine to make an empty queue-array implementation 3.13.5 Other applications


void ➢ When jobs are submitted to a printer, they are arranged in order of arrival. Thus,
essentially, jobs sent to a line printer are placed on a queue.
make_null ( QUEUE Q )
➢ Virtually every real-life line is (supposed to be) a queue. For instance, lines at
{
ticket counters are queues, because service is first-come first-served.
Q->q_size = 0;
➢ Another example concerns computer networks. There are many network setups of
Q->q_front = 1; personal computers in which the disk is attached to one machine, known as the
Q->q_rear = 0; file server. Users on other machines are given access to files on a first-come first-
served basis, so the data structure is a queue.
}
➢ Calls to large companies are generally placed on a queue when all operators are
3.13.4 Routines to enqueue-array implementation busy.
unsigned int ➢ In large universities, where resources are limited, students must sign a waiting list
succ( unsigned int value, QUEUE Q ) if all terminals are occupied. The student who has been at a terminal the longest
is forced off first, and the student who has been waiting the longest is the next
{
user to be allowed on.
if( ++value == Q->q_max_size )
value = 0;
return value;
}
void
enqueue( element_type x, QUEUE Q )
{
if( is_full( Q ) )
error("Full queue");
else
{
Q->q_size++;
Q->q_rear = succ( Q->q_rear, Q );
Q->q_array[ Q->q_rear ] = x;
}
}
C Programming and Data Structures 3.77 3.78 Linear Data Structures

REVIEW QUESTIONS 7. What are the pitfall encountered in singly linked list?
➢ The singly linked list has only forward pointer and no backward link is provided.
PART-A
Hence the traversing of the list is possible only in one direction. Backward
1. What do you mean by non-linear data structure? Give example. traversing is not possible.
➢ The non-linear data structure is the kind of data structure in which the data may ➢ Insertion and deletion operations are less efficient because for inserting the
be arranged in hierarchical fashion. For example- Trees and graphs. element at desired position the list needs to be traversed. Similarly, traversing of
the list is required for locating the element which needs to be deleted.
2. List the various operations that can be performed on data structure.
➢ Various operations that can be performed on the data structure are 8. What is Singly Linked List?
➢ A singly linked list is a type of linked list that is unidirectional, that is, it can be
 Create
traversed in only one direction from head to the last node (tail).
 Insertion of element
9. Define doubly linked list.
 Deletion of element ➢ Doubly linked list is a kind of linked list in which each node has two link fields.
 Searching for the desired element One link field stores the address of previous node and the other link field stores
 Sorting the elements in the data structure the address of the next node.

 Reversing the list of elements. 10. Write down the steps to modify a node in linked lists.

3. What is abstract data type o Enter the position of the node which is to be modified.
➢ The abstract datatype is special kind of datatype, whose behavior is defined by o Enter the new value for the node to be modified.
a set of values and set of operations. o Search the corresponding node in the linked list.
4. What is list ADT in data structure? o Replace the original value of that node by a new value.
➢ The list ADT is a collection of elements that have a linear relationship with each o Display the messages as “The node is modified”.
other. A linear relationship means that each element of the list has a unique 11. Difference between arrays and lists.
successor. ➢ In arrays any element can be accessed randomly with the help of index of array,
5. What Are Arrays in Data Structures? whereas in lists any element can be accessed by sequential access only.
➢ An array is a linear data structure that collects elements of the same data type ➢ Insertion and deletion of data is difficult in arrays on the other hand insertion
and stores them in contiguous and adjacent memory locations. Arrays work on and deletion of data is easy in lists.
an index system starting from 0 to (n-1), where n is the size of the array. 12. State the properties of LIST abstract data type with suitable example.
6. What is a linked list? ➢ It is linear data structure in which the elements are arranged adjacent to each
➢ A linked list is a set of nodes where each node has two fields ‘data’ and ‘link’. other.
The data field is used to store actual piece of information and link field is used ➢ It allows to store single variable polynomial.
to store address of next node. ➢ If the LIST is implemented using dynamic memory, then it is called linked list.
Example of LIST are- stacks, queues, linked list.
C Programming and Data Structures 3.79 3.80 Linear Data Structures

13. State the advantages of circular lists over doubly linked list. ➢ Understandability: ADT specifies what is to be done and does not specify the
➢ In circular list the next pointer of last node points to head node, whereas in implementation details. Hence code becomes easy to understand due to ADT.
doubly linked list each node has two pointers: one previous pointer and another ➢ Reusability: the ADT can be reused by some program in future.
is next pointer. 20. What is queue ADT?
➢ The main advantage of circular list over doubly linked list is that with the help ➢ Queue is an abstract data structure, somewhat like Stacks. Unlike stacks, a queue
of single pointer field we can access head node quickly. Hence some amount of is open at both its ends. One end is always used to insert data (enqueue) and the
memory get saved because in circular list only one pointer is reserved. other is used to remove data (dequeue). Queue follows First-In-First-Out
14. What are the advantages of doubly linked list over singly linked list? methodology, i.e., the data item stored first will be accessed first.
➢ The doubly linked list has two pointer fields. One field is previous link field, and 21. What is priority queue
another is next link field. Because of these two pointer fields we can access any ➢ A priority queue is a special type of queue in which each element is associated
node efficiently whereas in singly linked list only one pointer field is there which with a priority value. Elements are served on the basis of their priority. That is,
stores forward pointer. higher priority elements are served first. However, if elements with the same
15. Why is the linked list used for polynomial arithmetic? priority occur, they are served according to their order in the queue.
➢ We can have separate coefficient and exponent fields for representing each term 22. What is stack?
of polynomial. Hence there is no limit for exponent. We can have any number ➢ Stack is an abstract data type that serves as a collection of elements, with two
as an exponent. main operations: Push, which adds an element to the collection, and Pop, which
16. What is the advantage of linked list over arrays? removes the most recently added element that was not yet removed.
➢ The linked list makes use of the dynamic memory allocation. Hence the user can 23. How is Stack represented in Data Structure?
allocate or de allocate the memory as per his requirements. On the other hand, ➢ A stack may be represented in the memory in various ways. There are two main
the array makes use of the static memory location. Hence there are chances of ways: using a one-dimensional array and a single linked list.
wastage of the memory or shortage of memory for allocation. 24. List some applications of queue data structure.
17. What is the circular linked list? ➢ Managing requests on a single shared resource such as CPU scheduling and disk
➢ The circular linked list is a kind of linked list in which the last node is connected scheduling.
to the first node or head node of the linked list. ➢ Handling hardware or real-time systems interrupts.
18. What is the basic purpose of header of the linked list? ➢ Handling website traffic.
➢ The header node is the very first node of the linked list. Sometimes a dummy ➢ Routers and switches in networking.
value such - 999 is stored in the data field of header node. ➢ Maintaining the playlist in media players.
➢ This node is useful for getting the starting address of the linked list. 25. List some applications of stack data structure.
19. What is the advantage of an ADT? ➢ A Stack can be used for evaluating expressions consisting of operands and
operators.
➢ Change: the implementation of the ADT can be changed without making
changes in the client program that uses the ADT. ➢ Stacks can be used for Backtracking, i.e., to check parenthesis matching in an
expression.
C Programming and Data Structures 3.81
➢ It can also be used to convert one form of expression to another form. It can be
used for systematic Memory Management.

PART B

1. Explain Singly Link List with algorithm and examples.


2. How insertion and deletion are performed on a singly linked list? Explain with
pseudocode and examples
3. Explain Doubly Linked List with examples and algorithms.
4. Explain Array based implementation of List ADT with examples and pseudocode.
5. Explain Array based implementation of Stack ADT with examples.
6. Demonstrate the implementation of circular linked list with examples.
7. Explain the applications of stack with examples.
8. Write short notes on queue ADT.
9. How are insertion and deletion operations performed in a queue? Explain with
examples and pseudocode.
10. Explain the implementation of priority queue with examples and pseudocode.
11. Explain queue implementation using linked list with pseudocode and examples.
12. Explain queue implementation using stack with pseudocode and examples.

You might also like