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

Unit 2

Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
15 views

Unit 2

Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 30

UNIT-2

Queue
 A queue can be defined as an ordered list which enables insert operations to be performed at one
end called REAR and delete operations to be performed at another end called FRONT.

 Queue is referred to be as First In First Out list (FIFO).

 For example, people waiting in line for a rail ticket form a queue.

Operations performed on queue


The fundamental operations that can be performed on queue are listed as follows -

o Enqueue: The Enqueue operation is used to insert the element at the rear end of the queue. It
returns void.
o Dequeue: It performs the deletion from the front-end of the queue. It also returns the element which
has been removed from the front-end. It returns an integer value.
o Peek: This is the third operation that returns the element, which is pointed by the front pointer in the
queue but does not delete it.
o Queue overflow (isfull): It shows the overflow condition when the queue is completely full.
o Queue underflow (isempty): It shows the underflow condition when the Queue is empty, i.e., no
elements are in the Queue.

Implementation of queues

I. Array representation of Queue


 We can easily represent queue by using linear arrays. There are two variables i.e. front and
rear, that are implemented in the case of every queue.

1
 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.

Insert any element in a queue

 Check if the queue is already full by comparing rear to max - 1. if so, then return an overflow error.

 If the item is to be inserted as the first element in the list, in that case set the value of front and rear to 0
and insert the element at the rear end.

 Otherwise keep increasing the value of rear and insert each element one by one having rear as the
index.

Algorithm

Step 1: IF REAR = MAX - 1


Write OVERFLOW
Go to step
[END OF IF]

Step 2: IF FRONT = -1 and REAR = -1


SET FRONT = REAR = 0
2
ELSE
SET REAR = REAR + 1
[END OF IF]

Step 3: Set QUEUE [REAR] = VAL

Step 4: EXIT

Implementation Code

void insert (int queue[], int max, int front, int rear, int item)
{
if (rear == max-1)
{
printf("overflow");
}
else
{
if(front == -1 && rear == -1)
{
front = 0;
rear = 0;
}
else
{
rear = rear + 1;
}
queue[rear]=item;
}
}

Delete an element from the queue

 If, the value of front is -1 or value of front is greater than rear , write an underflow message and exit.

 Otherwise, keep increasing the value of front and return the item stored at the front end of the queue at
each time.

3
Algorithm

Step 1: IF FRONT = -1 or FRONT > REAR


Write UNDERFLOW
ELSE
SET VAL = QUEUE [FRONT]
SET FRONT = FRONT + 1
[END OF IF]

Step 2: EXIT

Implementation Code

int delete (int queue[], int max, int front, int rear)
{
int y;
if (front == -1 || front > rear)

{
printf("underflow");
}
else
{
y = queue[front];
if(front == rear)
{
front = rear = -1;
else
front = front + 1;
}
return y;
}
}

4
Drawback of array implementation

1. Memory wastage :
2. Deciding the array size

II. Linked List implementation of Queue


 In a linked queue, each node of the queue consists of two parts i.e. data part and the link part. Each
element of the queue points to its immediate next element in the memory.

 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.

Insert operation
The insert operation appends the queue by adding an element to the end of the queue. The new element
will be the last element of the queue.

Firstly, allocate the memory for the new node ptr by using the following statement.

Ptr = (struct node *) malloc (sizeof(struct node));

There can be the two scenario of inserting this new node ptr into the linked queue.

5
In the first scenario, we insert element into an empty queue. In this case, the condition front =
NULL becomes true. Now, the new element will be added as the only element of the queue and the next
pointer of front and rear pointer both, will point to NULL.

In the second case, the queue contains more than one element. The condition front = NULL becomes false.
In this scenario, we need to update the end pointer rear so that the next pointer of rear will point to the
new node ptr. Since, this is a linked queue, hence we also need to make the rear pointer point to the newly
added node ptr. We also need to make the next pointer of rear point to NULL.

Algorithm
o Step 1: Allocate the space for the new node PTR

o Step 2: SET PTR -> DATA = VAL

o Step 3: IF FRONT = NULL


SET FRONT = REAR = PTR
SET FRONT -> NEXT = REAR -> NEXT = NULL

ELSE
SET REAR -> NEXT = PTR
SET REAR = PTR

SET REAR -> NEXT = NULL


[END OF IF]

o Step 4: END

Code Implementation

ptr -> data = item;


if(front == NULL)
{
front = ptr;
rear = ptr;
front -> next = NULL;
rear -> next = NULL;
}

rear -> next = ptr;


rear = ptr;
rear->next = NULL;

6
Deletion
Deletion operation removes the element that is first inserted among all the queue elements. Firstly, we
need to check either the list is empty or not. The condition front == NULL becomes true if the list is empty,
in this case , we simply write underflow on the console and make exit.

Otherwise, we will delete the element that is pointed by the pointer front. For this purpose, copy the node
pointed by the front pointer into the pointer ptr. Now, shift the front pointer, point to its next node and
free the node pointed by the node ptr. This is done by using the following statements.

Algorithm
o Step 1: IF FRONT = NULL
Write “Underflow”
Go to Step 5
[END OF IF]
o Step 2: SET PTR = FRONT

o Step 3: SET FRONT = FRONT -> NEXT

o Step 4: FREE PTR

o Step 5: END

Code Implementation

ptr = front;
front = front -> next;
free(ptr);

7
Types of Queue

1. Simple Queue or Linear Queue


2. Circular Queue
3. Priority Queue
4. Double Ended Queue (or Deque)

1. Simple Queue or Linear Queue


 In Linear Queue, an insertion takes place from one end while the deletion occurs from
another end. The end at which the insertion takes place is known as the rear end, and the
end at which the deletion takes place is known as front end. It strictly follows the FIFO
rule.

 The major drawback of using a linear Queue is that insertion is done only from the rear
end. If the first three elements are deleted from the Queue, we cannot insert more elements
even though the space is available in a Linear Queue. In this case, the linear Queue shows
the overflow condition as the rear is pointing to the last element of the Queue.

2. Circular Queue
 In Circular Queue, all the nodes are represented as circular. It is similar to the linear Queue except
that the last element of the queue is connected to the first element. It is also known as Ring Buffer,
as all the ends are connected to another end.

 The drawback that occurs in a linear queue is overcome by using the circular queue. If the empty
space is available in a circular queue, the new element can be added in an empty space by simply
incrementing the value of rear.

 The main advantage of using the circular queue is better memory utilization.

8
3. Priority Queue
 It is a special type of queue in which the elements are arranged based on the priority. It is a special
type of queue data structure in which every element has a priority associated with it.
 Suppose some elements occur with the same priority, they will be arranged according to the FIFO
principle.
 Insertion in priority queue takes place based on the arrival, while deletion in the priority queue
occurs based on the priority.
 Priority queue is mainly used to implement the CPU scheduling algorithms.

 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. Suppose an array with elements 7, 5,
and 3 in the same order, so, insertion can be done with the same sequence, but the order of
deleting the elements is 3, 5, 7.
2) Descending priority queue - In descending priority queue, elements can be inserted in
arbitrary order, but only the largest element can be deleted first. Suppose an array with
elements 7, 3, and 5 in the same order, so, insertion can be done with the same sequence,
but the order of deleting the elements is 7, 5, 3.

9
4. Double Ended Queue (or Deque)
 In Deque or Double Ended Queue, insertion and deletion can be done from both ends of the queue
either from the front or rear. It means that we can insert and delete elements from both front and
rear ends of the queue

 Deque can be used as a palindrome checker means that if we read the string from both ends, then
the string would be the same.

There are two types of deque

1) Input restricted deque - As the name implies, in input restricted queue, insertion operation can be
performed at only one end, while deletion can be performed from both ends.

2) Output restricted deque - As the name implies, in output restricted queue, deletion operation can
be performed at only one end, while insertion can be performed from both ends.

10
Linked list
 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.

 A node in the linked list contains two parts, i.e., first is the data part and second is the address part.
The last node of the list contains a pointer to the null.
 In a linked list, every link contains a connection to another link.

 Using array data structure to organize the group of elements that are to be stored individually in the memory.

Limitations of array data structure

o The size of the array must be known in advance before using it in the program.
o 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.
o 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.

Overcomes the limitations of arrays (advantage of Linked list)

 Dynamic data structure: - It allocates the memory dynamically. All the nodes of the linked list are non-
contiguously stored in the memory and linked together with the help of pointers.

 Memory efficient: - In linked list, size is not a problem since we do not need to define its size at the time of
declaration. List grows as per the program's demand and limited to the available memory space.

 Insertion and deletion:- To insert or delete an element in an array, we have to shift the elements for creating
the space. Whereas, in linked list, instead of shifting, we just have to update the address of the pointer of the
node.
11
 Implementation - We can implement both stacks and queues using linked list.

Disadvantages of Linked list


o Memory usage - In linked list, node occupies more memory than array. Each node of the linked list
occupies two types of variables, i.e., one is a simple variable, and another one is the pointer variable.
o Traversal - Traversal is not easy in the linked list. If we have to access an element in the linked list,
we cannot access it randomly, while in case of array we can randomly access it by index. For
example, if we want to access the 3rd node, then we need to traverse all the nodes before it. So, the
time required to access a particular node is large.
o 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 pointer.

Operations performed on Linked list


o Insertion - This operation is performed to add an element into the list.
o Deletion - It is performed to delete an operation from the list.
o Display - It is performed to display the elements of the list.
o Search - It is performed to search an element from the list using the given key.

Types of Linked list


o Singly Linked list
o Doubly Linked list
o Circular Linked list
o Doubly Circular Linked list

1) Singly Linked list (One way chain)

 It is the commonly used linked list in programs. If we are talking about the linked list, it means it is a singly
linked list.

12
 The singly linked list is a data structure that contains two parts, i.e., one is the data part, and the other one
is the address part, which contains the address of the next or the successor node. The address part in a
node is also known as a pointer.

 Singly linked list as it contains only a single link. In this list, only forward traversal is possible; we
cannot traverse in the backward direction as it has only one link in the list.

Representation of a Linked list in Memory

13
Implementation of Singly Linked Lists

 Create nodes of singly linked lists using structures and link them using the next pointer.

struct node
{
int data;
struct node *next;
}
In the above representation, we have defined a user-defined structure named a node containing two members,
the first one is data of integer type, and the other one is the pointer (next) of the node type.

 Create nodes of singly linked lists using classes and link them using the next pointer.

//A class to create node

class Node {

public:

int data;

Node* next;

};

Each struct node has a data item and a pointer to another struct node. Let us create a simple Linked
List with three items to understand how this works.

/* Initialize nodes */
struct node *head;
struct node *one = NULL;
struct node *two = NULL;
struct node *three = NULL;

/* Allocate memory */
one = malloc(sizeof(struct node));
two = malloc(sizeof(struct node));
14
three = malloc(sizeof(struct node));

/* Assign data values */


one->data = 1;
two->data = 2;
three->data=3;

/* Connect nodes */
one->next = two;
two->next = three;
three->next = NULL;

/* Save address of first node in head */


head = one;

2) Doubly linked list (Two way chain)


 A doubly linked list is a list that has three parts in a single node, includes one data part, a pointer to
its previous node, and a pointer to the next node.

 The node in a doubly-linked list has two address parts; one part stores the address of the
next while the other part of the node stores the previous node's address. The initial node in the
doubly linked list has the NULL value in the address part, which provides the address of the
previous node.

struct node
{
int data;
struct node *next;
15
struct node *prev;
}

In the above implementation, we have defined a user-defined structure named a node with three
members, one is data of integer type, and the other two are the pointers, i.e., next and prev of the node
type. The next pointer variable holds the address of the next node, and the prev pointer holds the
address of the previous node. The type of both the pointers, i.e., next and prev is struct node as both the
pointers are storing the address of the node of the struct node type.

3) Circular linked list

 The only difference between the singly linked list and a circular linked list is that the last node
does not point to any node in a singly linked list, so its link part contains a NULL value. On the
other hand, the circular linked list is a list in which the last node connects to the first node, so
the link part of the last node holds the first node's address.

 The circular linked list has no starting and ending node. We can traverse in any direction, i.e., either
backward or forward.

 The representation of the circular linked list will be similar to the singly linked list.

struct node
{
16
int data;
struct node *next;
}

4) Doubly Circular linked list

 The doubly circular linked list has the features of both the circular linked list and doubly linked
list.

 In doubly circular linked list which the last node is attached to the first node and thus creates a
circle. It is a doubly linked list also because each node holds the address of the previous node
also.

 The main difference between the doubly linked list and doubly circular linked list is that the
doubly circular linked list does not contain the NULL value in the previous field of the node. As
the doubly circular linked contains three parts, i.e., two address parts and one data part so its
representation is similar to the doubly linked list.

 Representation is similar to the doubly linked list.

17
struct node
{
int data;
struct node *next;
struct node *prev;
}

Header Linked List


 A header linked list is a type of linked list that has a header node at the beginning of the list. In a
header linked list, HEAD points to the header node instead of the first node of the list.

 The header node does not represent an item in the linked list. This data part of this node is
generally used to hold any global information about the entire linked list. The next part of the header
node points to the first node in the list.

 A header linked list can be divided into two types:

1) Grounded header linked list that stores NULL in the last node’s next field.

2) Circular header linked list that stores the address of the header node in the next part of the
last node of the list.

18
Two-way Header List

19
Linked List Operations with Algorithms
A singly linked list is the most simple type of linked list, with each node containing some data as
well as a pointer to the next node. That is a singly linked list allows traversal of data only in one
way. There are several linked list operations that allow us to perform different tasks.

The basic linked list operations are:

Traversal – Access the nodes of the list.


Insertion – Adds a new node to an existing linked list.
Deletion – Removes a node from an existing linked list.
Search – Finds a particular element in the linked list.

1) Traverse a Linked List


Accessing the nodes of a linked list in order to process it is called traversing a linked list. Normally
we use the traverse operation to display the contents or to search for an element in the linked list.

Algorithm: Traverse
Step 1: [INITIALIZE] SET PTR = HEAD
Step 2: Repeat Steps 3 and 4 while PTR != NULL
Step 3: Apply process to PTR -> DATA
Step 4: SET PTR = PTR->NEXT
[END OF LOOP]
Step 5: EXIT

 We first initialize PTR with the address of HEAD. Now the PTR points to the first node of the linked list.
 A while loop is executed, and the operation is continued until PTR reaches the last node (PTR = NULL).
 Apply the process (display) to the current node.
 Move to the next node by making the value of PTR to the address of next node.

The following block of code prints all elements in a linked list in C.

struct node *ptr = head;

printf("Elements in the linked list are : ");

20
while (ptr != NULL)

printf("%d ", ptr->data);

ptr = ptr->next;

2) Inserting Elements to a Linked List


We will see how a new node can be added to an existing linked list in the following cases.

1. The new node is inserted at the beginning.


2. The new node is inserted at the end.
3. The new node is inserted after a given node.

1. Insert a Node at the beginning of a Linked list

Consider the linked list shown in the figure. Suppose we want to create a new node with data 24 and add it as
the first node of the list. The linked list will be modified as follows.

 Allocate memory for new node and initialize its DATA part to 24.
 Add the new node as the first node of the list by pointing the NEXT part of the new node to HEAD.
21
 Make HEAD to point to the first node of the list.

Algorithm: InsertAtBeginning

Step 1: IF AVAIL = NULL


Write OVERFLOW
Go to Step 7
[END OF IF]
Step 2: SET NEW_NODE = AVAIL
Step 3: SET AVAIL = AVAIL -> NEXT
Step 4: SET NEW_NODE -> DATA = VAL
Step 5: SET NEW_NODE -> NEXT = HEAD
Step 6: SET HEAD = NEW_NODE
Step 7: EXIT

Note that the first step of the algorithm checks if there is enough memory available to create a new
node. The second, and third steps allocate memory for the new node.

This algorithm can be implemented in C as follows:

struct node *new_node;

new_node = (struct node*) malloc(sizeof(struct node));

new_node->data = 24;

new_node->next = head;

head = new_node;

2. Insert a Node at the end of a Linked list

Take a look at the linked list in the figure. Suppose we want to add a new node with data 24 as the
last node of the list. Then the linked list will be modified as follows.

22
 Allocate memory for new node and initialize its DATA part to 24.
 Traverse to last node.
 Point the NEXT part of the last node to the newly created node.
 Make the value of next part of last node to NULL.

Algorithm: InsertAtEnd

Step 1: IF AVAIL = NULL


Write OVERFLOW
Go to Step 10
[END OF IF]
Step 2: SET NEW_NODE = AVAIL
Step 3: SET AVAIL = AVAIL -> NEXT
Step 4: SET NEW_NODE -> DATA = VAL
Step 5: SET NEW_NODE -> NEXT = NULL
Step 6: SET PTR = HEAD
Step 7: Repeat Step 8 while PTR -> NEXT != NULL
Step 8: SET PTR = PTR -> NEXT
[END OF LOOP]
Step 9: SET PTR -> NEXT = NEW_NODE
Step 10: EXIT

This can be implemented in C as follows,

struct node *new_node;

23
new_node = (struct node*) malloc(sizeof(struct node));
new_node->data = 24;
new_node->next = NULL;
struct node *ptr = head;
while(ptr->next != NULL){
ptr = ptr->next;
}
ptr->next = new_node;

3. Insert a Node after a given Node in a Linked list


The last case is when we want to add a new node after a given node. Suppose we want to add a new node
with value 24 after the node having data 9. These changes will be done in the linked list.

 Allocate memory for new node and initialize its DATA part to 24.
 Traverse the list until the specified node is reached.
 Change NEXT pointers accordingly.

Algorithm: InsertAfterAnElement

Step 1: IF AVAIL = NULL


24
Write OVERFLOW
Go to Step 12
[END OF IF]
Step 2: SET NEW_NODE = AVAIL
Step 3: SET AVAIL = AVAIL -> NEXT
Step 4: SET NEW_NODE -> DATA = VAL
Step 5: SET PTR = HEAD
Step 6: SET PREPTR = PTR
Step 7: Repeat Steps 8 and 9 while PREPTR -> DATA != NUM
Step 8: SET PREPTR = PTR
Step 9: SET PTR = PTR -> NEXT
[END OF LOOP]
Step 10 : PREPTR -> NEXT = NEW_NODE
Step 11: SET NEW_NODE -> NEXT = PTR
Step 12: EXIT

3) Deleting Elements from a Linked List


Let’s discuss how a node can be deleted from a linked listed in the following cases.

 The first node is deleted.


 The last node is deleted.
 The node after a given node is deleted.

1. Delete a Node from the beginning of a Linked list

Suppose we want to delete a node from the beginning of the linked list. The list has to be modified as
follows:

25
 Check if the linked list is empty or not. Exit if the list is empty.
 Make HEAD points to the second node.
 Free the first node from memory.

Algorithm: DeleteFromBeginning

Step 1: IF HEAD = NULL


Write UNDERFLOW
Go to Step 5
[END OF IF]
Step 2: SET PTR = HEAD
Step 3: SET HEAD = HEAD -> NEXT
Step 4: FREE PTR
Step 5: EXIT

This can be implemented in C as follows,

if(head == NULL)
{
printf("Underflow");
}
else
{
ptr = head;
head = head -> next;
free(ptr);
26
}

2. Delete last Node from a Linked list


Suppose we want to delete the last node from the linked list. The linked list has to be modified as follows:

 Traverse to the end of the list.


 Change value of next pointer of second last node to NULL.
 Free last node from memory.

Algorithm: DeleteFromEnd

Step 1: IF HEAD = NULL


Write UNDERFLOW
Go to Step 8
[END OF IF]
Step 2: SET PTR = HEAD
Step 3: Repeat Steps 4 and 5 while PTR -> NEXT != NULL
Step 4: SET PREPTR = PTR
Step 5: SET PTR = PTR -> NEXT
[END OF LOOP]
Step 6: SET PREPTR -> NEXT = NULL
Step 7: FREE PTR
Step 8: EXIT

Here we use two pointers PTR and PREPTR to access the last node and the second last node. This can be
implemented in C as follows,

27
if(head == NULL)
{
printf("Underflow");
}
else
{
struct node* ptr = head;
struct node* preptr = NULL;
while(ptr->next!=NULL){
preptr = ptr;
ptr = ptr->next;
}
preptr->next = NULL;
free(ptr);
}

3. Delete the Node after a given Node in a Linked list


Suppose we want to delete the that comes after the node which contains data 9.

 Traverse the list upto the specified node.


 Change value of next pointer of previous node(9) to next pointer of current node(10).

28
Algorithm: DeleteAfterANode

Step 1: IF HEAD = NULL


Write UNDERFLOW
Go to Step 10
[END OF IF]
Step 2: SET PTR = HEAD
Step 3: SET PREPTR = PTR
Step 4: Repeat Steps 5 and 6 while PREPTR -> DATA != NUM
Step 5: SET PREPTR = PTR
Step 6: SET PTR = PTR -> NEXT
[END OF LOOP]
Step 7: SET TEMP = PTR
Step 8: SET PREPTR -> NEXT = PTR -> NEXT
Step 9: FREE TEMP
Step 10 : EXIT

Implementation in C takes the following form:

if(head == NULL)
{
printf("Underflow");
}
else
{
struct node* ptr = head;
struct node* preptr = ptr;
while(ptr->data!=num){
preptr = ptr;
ptr = ptr->next;
}
struct node* temp = ptr;
preptr -> next = ptr -> next;
free(temp);
}

4) Search
Finding an element is similar to a traversal operation. Instead of displaying data, we have to check whether
the data matches with the item to find.

29
 Initialize PTR with the address of HEAD. Now the PTR points to the first node of the linked list.
 A while loop is executed which will compare data of every node with item.
 If item has been found then control goes to last step.

Algorithm: Search

Step 1: [INITIALIZE] SET PTR = HEAD


Step 2: Repeat Steps 3 and 4 while PTR != NULL
Step 3: If ITEM = PTR -> DATA
SET POS = PTR
Go To Step 5
ELSE
SET PTR = PTR -> NEXT
[END OF IF]
[END OF LOOP]
Step 4: SET POS = NULL
Step 5: EXIT

Search operation can be implemented in C as follows:

struct node* ptr = head;


struct node* pos = NULL;
while (ptr != NULL) {
if (ptr->data == item)
pos = ptr
printf("Element Found");
break;
else
ptr = ptr -> next;
}

30

You might also like