0% found this document useful (0 votes)
90 views62 pages

UNIT-I DS Notes

The document discusses data structures and provides details about linear and non-linear data structures. It defines common linear structures like arrays, stacks, queues and linked lists. Non-linear structures include trees and graphs. Abstract data types (ADTs) are also introduced, with examples for lists, stacks and queues provided. Implementation details are given for singly linked lists, including node structure, advantages, disadvantages and steps to create and traverse a linked list.

Uploaded by

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

UNIT-I DS Notes

The document discusses data structures and provides details about linear and non-linear data structures. It defines common linear structures like arrays, stacks, queues and linked lists. Non-linear structures include trees and graphs. Abstract data types (ADTs) are also introduced, with examples for lists, stacks and queues provided. Implementation details are given for singly linked lists, including node structure, advantages, disadvantages and steps to create and traverse a linked list.

Uploaded by

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

DATA STRUCTURES

UNIT-I
What is Data Structure
In computer terms, a data structure is a Specific way to store and organize data
in a computer's memory so that these data can be used efficiently later. Data
may be arranged in many different ways such as the logical or mathematical
model for a particular organization of data is termed as a data structure.

Classification of Data Structures

 Linear Data Structure


 Non-linear Data Structure

Linear Data Structure

• A data structure is said to be linear if its elements combine to form any specific
order. There are two techniques of representing such linear structure within
memory.
• The first way is to provide the linear relationships among all the elements
represented using linear memory location. These linear structures are termed as
arrays.

• The second technique is to provide a linear relationship among all the


elements represented by using the concept of pointers or links. These linear
structures are termed as linked lists.

The common examples of the linear data structure are:

• Arrays

• Queues

• Stacks

• Linked lists

Nonlinear Data Structure

This structure is mostly used for representing data that contains a hierarchical
relationship among various elements.

Examples of Non-Linear Data Structures are listed below:

• Graphs

• the family of trees and

• table of contents

Tree: In this case, data often contain a hierarchical relationship among various
elements. The data structure that reflects this relationship is termed as a rooted
tree graph or a tree.

Graph: In this case, data sometimes hold a relationship between the pairs of
elements which is not necessarily following the hierarchical structure. Such a
data structure is termed as a Graph

Abstract Data Types


Abstract Data type (ADT) is a type (or class) for objects whose behavior is
defined by a set of value and a set of operations.
The definition of ADT only mentions what operations are to be performed but
not how these operations will be implemented. It does not specify how data will
be organized in memory and what algorithms will be used for implementing the
operations. It is called “abstract” because it gives an implementation-
independent view. The process of providing only the essentials and hiding the
details is known as abstraction.

The user of data type does not need to know how that data type is implemented,
for example, we have been using Primitive values like int, float, char data types
only with the knowledge that these data type can operate and be performed on
without any idea of how they are implemented. So a user only needs to know
what a data type can do, but not how it will be implemented. Think of ADT as a
black box which hides the inner structure and design of the data type. Now
we’ll define three ADTs namely List ADT, Stack ADT, Queue ADT.

List ADT

A list contains elements of the same type arranged in sequential order and
following operations can be performed on the list.

get() – Return an element from the list at any given position.

insert() – Insert an element at any position of the list.

remove() – Remove the first occurrence of any element from a non-empty list.

removeAt() – Remove the element at a specified location from a non-empty list.

replace() – Replace an element at any position by another element.

size() – Return the number of elements in the list.

isEmpty() – Return true if the list is empty, otherwise return false.

isFull() – Return true if the list is full, otherwise return false.

Stack ADT

A Stack contains elements of the same type arranged in sequential order. All
operations take place at a single end that is top of the stack and following
operations can be performed:

push() – Insert an element at one end of the stack called top.

pop() – Remove and return the element at the top of the stack, if it is not empty.
peek() – Return the element at the top of the stack without removing it, if the
stack is not empty.

size() – Return the number of elements in the stack.

isEmpty() – Return true if the stack is empty, otherwise return false.

isFull() – Return true if the stack is full, otherwise return false.

Queue ADT

A Queue contains elements of the same type arranged in sequential order.


Operations take place at both ends, insertion is done at the end and deletion is
done at the front. Following operations can be performed:

enqueue() – Insert an element at the end of the queue.

dequeue() – Remove and return the first element of the queue, if the queue is
not empty.

peek() – Return the element of the queue without removing it, if the queue is not
empty.

size() – Return the number of elements in the queue.

isEmpty() – Return true if the queue is empty, otherwise return false.

isFull() – Return true if the queue is full, otherwise return false.

From these definitions, we can clearly see that the definitions do not specify
how these ADTs will be represented and how the operations will be carried out.
There can be different ways to implement an ADT, for example, the List ADT
can be implemented using arrays, or singly linked list or doubly linked list.
Similarly, stack ADT and Queue ADT can be implemented using arrays or
linked lists.

Data Structure: Singly Linked list

Singly linked list is a basic linked list type. Singly linked list is a collection of
nodes linked together in a sequential way where each node of singly linked list
contains a data field and an address field which contains the reference of the
next node. Singly linked list can contain multiple data fields but should contain
at least single address field pointing to its connected next node.
To perform any operation on a linked list we must keep track/reference of the
first node which may be referred by head pointer variable. In singly linked list
address field of last node must contain a NULL value specifying end of the list.

Basic structure of a singly linked list

Each node of a singly linked list follows a common basic structure. In a node
we can store more than one data fields but we need at least single address field
to store the address of next connected node.

struct node {
int data; // Data
struct node * next; // Address
};

Advantages of Singly linked list

There are several points about singly linked list that makes it an important data
structure.

 Singly linked list is probably the most easiest data structure to implement.
 Insertion and deletion of element can be done easily.
 Insertion and deletion of elements doesn't requires movement of all
elements when compared to an array.
 Requires less memory when compared to doubly, circular or doubly
circular linked list.
 Can allocate or deallocate memory easily when required during its
execution.
 It is one of most efficient data structure to implement when traversing in
one direction is required.

Disadvantages of Singly linked list

After seeing the advantages of singly linked list. Singly linked list also has some
disadvantages over other data structures.

 It uses more memory when compared to an array.


 Since elements are not stored sequentially hence requires more time to
access each elements of list.
 Traversing in reverse is not possible in case of Singly linked list when
compared to Doubly linked list.
 Requires O(n) time on appending a new node to end. Which is relatively
very high when compared to array or other linked list.

How to create a linked list?

Step by step descriptive logic to create a linked list.

1. The first step of creating linked list of n nodes starts from defining node
structure. We need a custom type to store our data and location of next
linked node. Let us define our custom node structure
2. struct node {
3. int data;
4. struct node *next;
};

Where data is the data you want to store in list. *next is pointer to the
same structure type. The *next will store location of next node if exists
otherwise NULL.

Note: The node structure may vary based on your requirement. You can
also have user defined types as node data section.

5. Declare a pointer to node type variable to store link of first node of linked
list. Say struct node *head;.

Note: You can also declare variable of node type along with node
structure definition.

6. Input number of nodes to create from user, store it in some variable say n.
7. Declare two more helper variable of node type, say struct node
*newNode, *temp;.
8. If n > 0 then, create our first node i.e. head node. Use dynamic memory
allocation to allocate memory for a node. Say head = (struct
node*)malloc(sizeof(struct node));.
9. If there is no memory to allocate for head node i.e. head == NULL. Then
print some error message and terminate program, otherwise move to
below step.
10.Input data from user and assign to head using head->data = data;.
11.At first head node points to NULL. Hence, assign head->next = NULL;.
12.Now, we are done with head node we should move to creation of other
nodes. Copy reference of head to some other temporary variable, say
temp = head;. We will use temp to store reference of previous node.
13.Allocate memory and assign memory reference to newNode, say
newNode = (struct node*)malloc(sizeof(node));.
14.If memory got allocated successfully then read data from user and assign
to data section of new node. Say newNode->data = data;.
15.Make sure new node points to NULL.
16.Now link previous node with newly created node i.e. temp->next =
newNode;.
17.Make current node as previous node using temp = temp->next;.
18.Repeat step 10-14 for remaining n - 2 other nodes.

How to traverse a linked list?

Step by step descriptive logic to traverse a linked list.

1. Create a temporary variable for traversing. Assign reference of head node


to it, say temp = head.
2. Repeat below step till temp != NULL.
3. temp->data contains the current node data. You can print it or can
perform some calculation on it.
4. Once done, move to next node using temp = temp->next;.
5. Go back to 2nd step.

How to insert a node in the beginning of the singly linked list. Algorithm to
insert a node at the beginning of Singly linked list. Steps to insert a new node at
the start of a singly linked list.

Algorithm to insert node at the beginning of Singly Linked List


Being:
createSinglyLinkedList (head)
alloc (newNode)
If (newNode == NULL) then
write ('Unable to allocate memory')
End if
Else then
read (data)wo
newNode.data ← data
newNode.next ← head
head ← newNode
End else
End

Steps to insert node at the beginning of singly linked list

1. Create a new node, say newNode points to the newly created node.

2. Link the newly created node with the head node, i.e. the newNode will
now point to head node.
3. Make the new node as the head node, i.e. now head node will point to
newNode.

Algorithm to insert node at the end of singly linked list. Steps to insert a new
node at the end of singly linked list.

Algorithm to insert node at the end of a Singly Linked List


Begin:
createSinglyLinkedList (head)
alloc (newNode)
If (newNode == NULL) then
write ('Unable to allocate memory')
End if
Else then
read (data)
newNode.data ← data
newNode.next ← NULL
temp ← head
While (temp.next != NULL) do
temp ← temp.next
End while
temp.next ← newNode
End else
End

Steps to insert node at the end of Singly linked list

1. Create a new node and make sure that the address part of the new node
points to NULL i.e. newNode->next=NULL
2. Traverse to the last node of the linked list and connect the last node of the
list with the new node, i.e. last node will now point to new node.
(lastNode->next = newNode).

Algorithm to insert node at the middle of singly Linked List

Input : n position to insert data in the list


Begin:
createSinglyLinkedList (head)
alloc (newNode)
If (newNode == NULL) then
write ('Unable to allocate memory.')
End if
Else then
read (data)
newNode.data ← data
temp ← head
For i ← 2 to n-1
temp ← temp.next
If (temp == NULL) then
break
End if
End for
If (temp != NULL) then
newNode.next ← temp.next
temp.next ← newNode
End if
End else
End

Steps to insert node at the middle of Singly Linked List

1. Create a new node.

2. Traverse to the n-1th position of the linked list and connect the new node
with the n+1th node. Means the new node should also point to the same
node that the n-1th node is pointing to. (newNode->next = temp->next
where temp is the n-1th node).

3. Now at last connect the n-1th node with the new node i.e. the n-1th node
will now point to new node. (temp->next = newNode where temp is the
n-1th node).
Algorithm to delete first node from singly linked list in C. Steps to delete first
node from singly linked list.
Algorithm to delete first node from Singly Linked List

Input: head of the linked list


Begin:
If (head != NULL) then
toDelete ← head
head ← head.next
unalloc (toDelete)
End if
End

Steps to delete first node from Singly Linked List

1. Copy the address of first node i.e. head node to some temp variable say
toDelete.
2. Move the head to the second node of the linked list i.e. head = head-
>next.

3. Disconnect the connection of first node to second node.

4. Free the memory occupied by the first node.

Algorithm to delete last node from a singly linked list. Steps to remove last
node from singly linked list.

Algorithm to delete last node of Singly Linked List


Input : head node of the linked list
Begin:
If (head == NULL) then
write ('List is already empty')
End if
Else then
toDelete ← head
secondLastNode ← head
While (toDelete.next != NULL) do
secondLastNode ← toDelete
toDelete ← toDelete.next
End while
If (toDelete == head) then
head ← NULL
End if
Else then
secondLastNode.next ← NULL
End else
unalloc (toDelete)
End else
End

Steps to delete last node of a Singly Linked List

1. Traverse to the last node of the linked list keeping track of the second last
node in some temp variable say secondLastNode.

2. If the last node is the head node then make the head node as NULL else
disconnect the second last node with the last node i.e. secondLastNode-
>next = NULL.
3. Free the memory occupied by the last node.

Algorithm to delete middle node from singly linked list. Steps to delete middle
node from singly linked list.

Algorithm to delete middle node of Singly Linked List

Input : head node of the linked list


n node to be deleted
Begin:
If (head == NULL) then
write ('List is already empty')
End if
Else then
toDelete ← head
prevNode ← head
For i←2 to n do
prevNode ← toDelete
toDelete ← toDelete.next
If (toDelete == NULL) then
break
End if
End for
If (toDelete != NULL) then
If (toDelete == head) then
head ← head.next
End if
prevNode.next ← toDelete.next
toDelete.next ← NULL
unalloc (toDelete)
End if
End else
End

Steps to delete middle node of Singly Linked List

1. Traverse to the nth node of the singly linked list and also keep reference of
n-1th node in some temp variable say prevnode.

2. Reconnect the n-1th node with the n+1th node i.e. prevNode->next =
toDelete->next (Where prevNode is n-1th node and toDelete node is the
nth node and toDelete->next is the n+1th node).

3. Free the memory occupied by the nth node i.e. toDelete node.

Algorithm to count total nodes in a singly linked list.

Algorithm to count number of nodes in Singly Linked List


Input : head node of the linked list
Begin:
count ← 0
If (head != NULL) then
temp ← head
While (temp != NULL) do
count ← count + 1
temp ← temp.next
End while
End if
write ('Total nodes in list =' + count)
End

How to search an element in linked list?

Search an element in linked list is fairly similar to how you search an element in
arrays. Here we will learn to perform linear search on singly linked list.

Step by step descriptive logic to search an element in linked list.

1. Input element to search from user. Store it in some variable say


keyToSearch.
2. Declare two variable one to store index of found element and other to
iterate through list. Say index = 0; and struct node *curNode = head;
3. If curNode is not NULL and its data is not equal to keyToSearch. Then,
increment index and move curNode to its next node.
4. Repeat step 3 till curNode != NULL and element is not found, otherwise
move to 5th step.
5. If curNode is not NULL, then element is found hence return index
otherwise -1.

Data Structure : Doubly Linked List

Doubly linked list is a collection of nodes linked together in a sequential way.


Each node of the list contains two parts (as in singly linked list) data part and the
reference or address part. The basic structure of node is shown in the below
image:
Doubly linked list is almost similar to singly linked list except it contains two
address or reference fields, where one of the address field contains reference of
the next node and other contains reference of the previous node. First and last
node of a linked list contains a terminator generally a NULL value, that
determines the start and end of the list. Doubly linked list is sometimes also
referred as bi-directional linked list since it allows traversal of nodes in both
direction. The basic structure of a doubly linked list is represented as:

Dou
bly Linked List

Since doubly linked list allows the traversal of nodes in both direction hence we
can keep track of both first and last nodes.

Basic structure of a doubly linked list

The basic structure of a doubly linked list contains a data field and two address
fields. Here is how it can be represented in C programming language.

struct node {
int data; // Data field
struct node * prev; // Address of previous node
struct node * next; // Address of next node
};

Advantages of Doubly linked list

Doubly linked list is one of the important data structures. Here are various
advantages of doubly linked list.
 As like singly linked list it is the easiest data structures to implement.
 Allows traversal of nodes in both direction which is not possible in singly
linked list.
 Deletion of nodes is easy when compared to singly linked list, as in singly
linked list deletion requires a pointer to the node and previous node to be
deleted. Which is not in case of doubly linked list we only need the
pointer which is to be deleted.
 Reversing the list is simple and straightforward.
 Can allocate or de-allocate memory easily when required during its
execution.
 It is one of most efficient data structure to implement when traversing in
both direction is required.

Disadvantages of Doubly linked list

Not many but doubly linked list has few disadvantages also which can be listed
below:

 It uses extra memory when compared to array and singly linked list.
 Since elements in memory are stored randomly, hence elements are
accessed sequentially no direct access is allowed.

Applications/Uses of doubly linked list in real life

There are various application of doubly linked list in the real world. Some of
them can be listed as:

 Doubly linked list can be used in navigation systems where both front
and back navigation is required.
 It is used by browsers to implement backward and forward navigation of
visited web pages i.e. back and forward button.
 It is also used by various application to implement Undo and Redo
functionality.
 It can also be used to represent deck of cards in games.
 It is also used to represent various states of a game.

Algorithm to create and traverse doubly linked list.


Doubly Linked List

Algorithm to create Doubly Linked list


Begin:
alloc (head)
If (head == NULL) then
write ('Unable to allocate memory')
End if
Else then
read (data)
head.data ← data;
head.prev ← NULL;
head.next ← NULL;
last ← head;
write ('List created successfully')
End else
End

Algorithm to traverse or display Doubly linked list from beginning

Input : head {Pointer to the first node of the list}


Begin:
If (head == NULL) then
write ('List is empty')
End if
Else then
temp ← head;
While (temp != NULL) do
write ('Data = ', temp.data)
temp ← temp.next;
End while
End else
End
Algorithm to traverse or display Doubly linked list from end

Input : last {Pointer to the last node of the list}


Begin:
If (last == NULL) then
write ('List is empty')
End if
Else then
temp ← last;
While (temp != NULL) do
write ('Data = ', temp.data)
temp ← temp.prev;
End while
End else
End

Steps to create Doubly linked list

1. Create a head node and assign some data to its data field.
2. Make sure that the previous and next address field of the head node must
point to NULL.
3. Make the head node as last node.

If you want to create more nodes then follow these steps:

1. Create a new node and assign some data to its data field.

2. Make sure that the next address field of new node must point to NULL.
3. Link the new node previous address field with lastNode.

4. Link the lastNode next address field with newNode.

5. Move the lastNode to newNode i.e. last node will now point to new node.

6. Repeat Steps 4-8 if you want to add more nodes to the list.

Algorithm to insert node at the beginning of a Doubly linked list

Input : head {A pointer pointing to the first node of the list}


Begin:
alloc (newNode)
If (newNode == NULL) then
write ('Unable to allocate memory')
End if
Else then
read (data)
newNode.data ← data;
newNode.prev ← NULL;
newNode.next ← head;

head.prev ← newNode;
head ← newNode;
write('Node added successfully at the beginning of List')
End else
End

Algorithm to insert a node at the end of Doubly linked list


Input : last {Pointer to the last node of doubly linked list}
Begin:
alloc (newNode)
If (newNode == NULL) then
write ('Unable to allocate memory')
End if
Else then
read (data)
newNode.data ← data;
newNode.next ← NULL;
newNode.prev ← last;

last.next ← newNode;
last ← newNode;
write ('Node added successfully at the end of List')
End else
End
Algorithm to insert node in a doubly linked list.

Algorithm to insert node at any position of a Doubly linked list

Input : head {Pointer to the first node of doubly linked list}


: last {Pointer to the last node of doubly linked list}
: N {Position where node is to be inserted}
Begin:
temp ← head
For i←1 to N-1 do
If (temp == NULL) then
break
End if
temp ← temp.next;
End for
If (N == 1) then
insertAtBeginning()
End if
Else If (temp == last) then
insertAtEnd()
End if
Else If (temp != NULL) then
alloc (newNode)
read (data)

newNode.data ← data;
newNode.next ← temp.next
newNode.prev ← temp
If (temp.next != NULL) then
temp.next.prev ← newNode;
End if
temp.next ← newNode;
write('Node added successfully')
End if
End

Steps to insert a new node in Doubly linked list

We have supposed that we want to insert a node at 3rd position.

1. Traverse to N-1 node in the list. Where N is the position to insert. Say
temp now points to N-1th node.

2. Create a newNode that is to be inserted and assign some data to its data
field.

3. Connect the next address field of newNode with the node pointed by next
address field of temp node.
4. Connect the previous address field of newNode with the temp node.

5. Check if temp->next is not NULL then, connect the previous address


field of node pointed by temp.next to newNode.

6. Connect the next address field of temp node to newNode i.e. temp->next
will now point to newNode.
7. Final list

Algorithm to delete node from beginning


Input: head {Pointer to first node of the linked list}
Begin:
If (head == NULL) then
write ('Can't delete from an empty list')
End if
Else then
toDelete ← head;
head ← head.next;
head.prev ← NULL;
unalloc (toDelete)
write ('Successfully deleted first node from the list')
End if
End

Algorithm to delete node from end of a doubly linked list

Input: last {Pointer to last node of the linked list}


Begin:
If (last == NULL) then
write ('Can't delete from an empty list')
End if
Else then
toDelete ← last;
last ← last.prev;
last.next ← NULL;
unalloc (toDelete)
write ('Successfully deleted last node from the list')

End if
End

Algorithm to delete node from any position of a doubly linked list

Input : head {Pointer to the first node of the list}


last {Pointer to the last node of the list}
N {Position to be deleted from list}
Begin:
current ← head;
For i ← 1 to N and current != NULL do
current ← current.next;
End for
If (N == 1) then
deleteFromBeginning()
End if
Else if (current == last) then
deleteFromEnd()
End if
Else if (current != NULL) then
current.prev.next ← current.next
If (current.next != NULL) then
current.next.prev ← current.prev;
End if
unalloc (current)
write ('Node deleted successfully from ', N, ' position')
End if
Else then
write ('Invalid position')
End if
End

Algorithm to delete a node from doubly linked list.


Steps to delete node from any position of a doubly linked list

Let us suppose that we want to delete node from 2nd position.

1. Traverse to Nth node of the linked list, lets say a pointer current points to
Nth node in our case 2 node.

2. Link the node behind current node with the node ahead of current node,
which means now the N-1th node will point to N+1th node of the list.
Which can be implemented as current->prev->next = current->next.

3. If N+1th node is not NULL then link the N+1th node with N-1th node i.e.
now the previous address field of N+1th node will point to N-1th node.
Which can be implemented as current->next->prev = current->prev.
4. Finally delete the current node from memory and you are done.

Algorithm to reverse a doubly linked list.

Doubly Linked List

Dou
bly Linked List Reversed

Algorithm to reverse a doubly linked list

Input : head {Pointer to first node of the list}


last {Pointer to last node of the list}
Begin:
current ← head;
While (current != NULL) do
temp ← current.next;
current.next ← current.prev;
current.prev ← temp;

current ← temp;
End while
temp ← head;
head ← last;
last ← temp;
End

Steps to reverse a doubly linked list

There are various methods to reverse a doubly linked list. Here I am using the
simplest approach to reverse the list.

1. To reverse the list we start with the first node. Say a pointer current keeps
track of the current node. Now initially current points to head node.

2. Swap the previous and next pointer fields of current node.

3. Move the position of current pointer to its next node. In general, now
current.prev holds the address of next node.
4. Repeat Step 2-3 until current pointer becomes NULL.
5. When, the current pointer becomes NULL then the list will look
something like.

6. Finally, swap the head and last pointers and you are done.

7. Now, if you compare the above image to the below given image you will
find both are similar linked list.

Data Structure : Circular Linked List

A circular linked list is basically a linear linked list that may be singly or
doubly. The only difference is that there is no any NULL value terminating the
list. In fact in the list every node points to the next node and last node points to
the first node, thus forming a circle. Since it forms a circle with no end to stop
hence it is called as circular linked list.

In circular linked list there can be no starting or ending node, whole node can be
traversed from any node. In order to traverse the circular linked list only once
we need to traverse entire list until the starting node is not traversed again.
A circular linked list can be implemented using both singly linked list and
doubly linked list. Here is the logical structure of a circular linked list.

Basic structure of Circular linked list

Circ
ular Linked List

Dou
bly Circular Linked List

Advantages of a Circular linked list

 Entire list can be traversed from any node.


 Circular lists are the required data structure when we want a list to be
accessed in a circle or loop.
 Despite of being singly circular linked list we can easily traverse to its
previous node, which is not possible in singly linked list.

Disadvantages of Circular linked list

 Circular list are complex as compared to singly linked lists.


 Reversing of circular list is a complex as compared to singly or doubly
lists.
 If not traversed carefully, then we could end up in an infinite loop.
 Like singly and doubly lists circular linked lists also doesn’t supports
direct accessing of elements.

Applications/Uses of Circular linked list in real life


 Circular lists are used in applications where the entire list is accessed one-
by-one in a loop. Example: Operating systems may use it to switch
between various running applications in a circular loop.
 It is also used by Operating system to share time for different users,
generally uses Round-Robin time sharing mechanism.
 Multiplayer games uses circular list to swap between players in a loop.

Basic operations on Circular linked list

 Creation of list
 Traversal of list
 Insertion of node
o At the beginning of list
o At any position in the list
 Deletion of node
o Deletion of first node
o Deletion of node from middle of the list
o Deletion of last node Counting total number of nodes

 Searching
 Reversing of list

How to create a circular linked list of n nodes and display all elements of the list

Algorithm to create and traverse a Circular linked list.

Algorithm to create Circular linked list

Input : N {Total number of nodes to be created}


Being:
alloc (head)
read (data)
head.data ← data;
head.next ← NULL;
prevNode ← head;
For count ← 2 to N do
alloc (newNode)
read (data)
newNode.data ← data;
newNode.next ← NULL;
prevNode.next ← newNode;
prevNode ← newNode;
End for
prevNode.next ← head;
End

Algorithm to traverse Circular linked list

Input : head {Pointer to the first node of the list}


Begin:
If (head == NULL) then
write ('List is empty')
Else then
current ← head;
Do
write ('Data =', current.data)
current ← current.next;
While (current != head)
End if
End

Steps to create circular linked list

The creation steps of a circular linked list is almost similar as of singly linked
list. Circular linked list only differs only differs in the last stage of its creation
as of singly linked list.

Follow these steps to create a circular linked list.

1. Create a head node and assign some data to its data field.
2. Make sure that the next pointer field of head node should point to NULL.

3. Now head node has been created that points to the first node of the list.
Lets take another pointer that also points to the first node say prevNode
pointer.

4. Create a newNode and assign some more value to its data field and also
do sure that next pointer field of newNode should point to NULL.

5. Now connect the previous node with newly created node i.e. connect the
next pointer field of prevNode with the newNode. So that next pointer
field of prevNode points to newNode.
6. Move the prevNode ahead i.e. prevNode should point to newNode which
can be done as prevNode = prevNode.next.

8. Repeat step 4-6 till N (where N is the total number of nodes to be


created).

9. After all nodes have been created. Now at final stage we have to connect
the last node with the first node in order to make it circular. Therefore,
now connect the next pointer field of prevNode with the head node i.e.
prevNode.next = head (Since prevNode points to last node of the list) and
you are done.
DATA STRUCTURE – STACK:

A stack is an abstract data type ADT, commonly used in most programming


languages. It is named stack as it behaves like a real-world stack, for example −
deck of cards or pile of plates etc.

A real-world stack allows operations at one end only. For example, we can
place or remove a card or plate from top of the stack only. Likewise, Stack ADT
allows all data operations at one end only. At any given time, We can only
access the top element of a stack.
This feature makes it LIFO data structure. LIFO stands for Last-in-first-out.
Here, the element which is placed inserted or added last, is accessed first. In
stack terminology, insertion operation is called PUSH operation and removal
operation is called POP operation.

Stack Representation
Below given diagram tries to depict a stack and its operations −
A stack can be implemented in two ways

 By using Arrays
 By using Linked List

Stack can either be a fixed size one or it may have a sense of dynamic
resizing.

Here, we are going to implement stack using arrays which makes it a


fixed size stack implementation.

Basic Operations
Stack operations may involve initializing the stack, using it and then de-
initializing it. Apart from these basic stuffs, a stack is used for the
following two primary operations –
push − pushing storing an element on the stack.
pop − removing accessing an element from the stack.
When data is PUSHed onto stack.
To use a stack efficiently we need to check status of stack as well. For the same

purpose, the following functionality is added to stacks –

peek − get the top data element of the stack, without removing it.

isFull − check if stack is full.

isEmpty − check if stack is empty.


At all times, we maintain a pointer to the last PUSHed data on the stack. As
this pointer always represents the top of the stack, hence named top. The top
pointer provides top value of the stack without actually removing it.
First we should learn about procedures to support stack functions −

Algorithm of peek function –


begin
return stack[top]
end
Implementation of peek function in C programming language –

int peek()

return stack[top];

isfull
Algorithm of isfull function –

begin

if top equals to MAXSIZE

return true

else

return false

endif

end

Implementation of isfull function in C programming language –

bool isfull()

if(top == MAXSIZE)
return true;

else

return false;

isempty
Algorithm of isempty function –

Begin
If top is less than 0
Return true
Else
Return false
Endif
end

Implementation of isempty function in C programming language is slightly


different.

We initialize top at -1, as index in array starts from 0.

So we check if top is below zero or -1 to determine if stack is empty.

Here's the code −PUSH Operation

bool isempty()
{
if(top == -1)
return true;
else
return false;
}
The process of putting a new data element onto stack is known as PUSH
Operation. Push operation involves series of steps −
Step 1 − Check if stack is full.
Step 2 − If stack is full, produce error and exit.
Step 3 − If stack is not full, increment top to point next empty space.
Step 4 − Add data element to the stack location, where top is pointing.
Step 5 − return success.

Algorithm for PUSH


operation

A simple algorithm for Push operation can be derived as follows –


Begin
procedure
push: stack,
data
if stack is
full
return null
endif

top←top+1

stack[top] ← data end procedure

Implementation of this algorithm in C, is very easy. See the below code –

void push(int data)


{
if(isFull())
{
printf("Could not insert data, Stack is full.\n");
}
Else
{
top = top + 1;
stack[top] = data;
}

Pop Operation
Accessing the content while removing it from stack, is known as pop
operation. In array implementation of pop operation, data element is not
actually removed, instead top is decremented to a lower position in stack to
point to next value. But in linked-list implementation, pop actually removes
data element and deallocates memory space.
A POP operation may involve the following steps −
Step 1 − Check if stack is empty.
Step 2 − If stack is empty, produce error and exit.
Step 3 − If stack is not empty, access the data element at which top is
pointing.
Step 4 − Decrease the value of top by 1.
Step 5 − return success.
Algorithm for POP operation
A simple algorithm for Pop operation can be derivedas follows −

begin:
if stack is empty
return null
endif

data ← stack[top]

top ← top - 1

return data end


Implementation of this algorithm in C, is shown below −
int pop(int data)
{
if(isempty())
{
printf("Could not retrieve data, Stack is em pty.\n");
}
else
{
data = stack[top];
top = top - 1;
return data;
}
}

1. write a c progarm to implement stack using linked list and


perform the operations i) push ii) pop iii) display

Test case 1:
Enter no.of students
3
Enter id name marks
11 gopal 520
Enter id name marks
24 teja 560
Enter id name marks
41 dell 420
data in stack
41 dell 420
24 teja 560
11 gopal 520
after pop the top node
24 teja 560
11 gopal 520

Test case 2:
Enter no.of students
5
Enter id name marks
501 manoj 540
Enter id name marks
504 ajay 420
Enter id name marks
530 abhishek 390
Enter id name marks
564 sirish 400
Enter id name marks
581 mahesh 480
data in stack
581 mahesh 480
564 sirish 400
530 abhishek 390
504 ajay 420
501 manoj 540
after pop the top node
564 sirish 400
530 abhishek 390
504 ajay 420
501 manoj 540

*/

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct stack {
int sno;
char sname[20];
int tmarks;
struct stack* next;
};
struct stack* top=NULL;
void push(int no,char name[],int marks){
struct stack* temp=(struct stack*)malloc(sizeof(struct stack));
temp->sno=no;
strcpy(temp->sname,name);
temp->tmarks=marks;
temp->next=top;
top=temp;
}
void pop(){
struct stack* dtemp;
//dtemp=top;
if(top==NULL){
printf("Stack is empty\n");
}
else{
dtemp=top;
top=top->next;
dtemp->next=NULL;
free(dtemp);
}

}
void display(){
struct stack* disp;
if(top==NULL){
printf("stack is empty\n");
}
else{
disp=top;

while(disp!=NULL){
printf("%d %s %d\n",disp->sno,disp->sname,disp->tmarks);
disp=disp->next;
}
}
}
int main(){
int i,n,id,marks;
char sname[10];
printf("Enter no.of students\n");
scanf("%d",&n);
for(i=0;i<n;i++){
printf("Enter id name marks\n");
scanf("%d %s %d",&id,sname,&marks);
push(id,sname,marks);
}
printf("data in stack\n");
display();
pop();
printf("after pop the top node\n");
display();
}

2.
/*
write a c program to implement stack using array and perform the
operations
i) push ii) pop iii) display

Test case 1:
Enter n value
5
Enter elements to stack
45
Enter elements to stack
23
Enter elements to stack
67
Enter elements to stack
12
Enter elements to stack
86
Elements in stack
86
12
67
23
45
After pop the top element
12
67
23
45
*/
#include <stdio.h>
#define SIZE 100

int stack[SIZE];
int top = -1;
void push(int value)
{
if(top<SIZE-1)
{
if (top < 0)
{
stack[0] = value;
top = 0;
}
else
{
stack[top+1] = value;
top++;
}
}
else
{
printf("Stackoverflow!!!!\n");
}
}
int pop()
{
if(top >= 0)
{
int n = stack[top];
top--;
return n;
}
}
void display()
{
int i;
if(top==0){
printf("stack is empty\n");
}
else{
for(i=top;i>=0;i--)
{
printf("%d\n",stack[i]);
}
}
}
int main()
{
int i,n,x;
printf("Enter n value\n");
scanf("%d",&n);
for(i=0;i<n;i++){
printf("Enter elements to stack\n");
scanf("%d",&x);
push(x);
}
printf("Elements in stack\n");
display();
pop();
printf("After pop the top element\n");
display();
return 0;
}
Stack Applications
Applications of stack:
 Balancing of symbols
 Infix to Postfix /Prefix conversion
 Redo-undo features at many places like editors, photoshop.
 Forward and backward feature in web browsers
 Used in many algorithms like Tower of Hanoi, tree traversals, stock span
problem, histogram problem.
 Other applications can be Backtracking, Knight tour problem, rat in a
maze, N queen problem and sudoku solver
 In Graph Algorithms like Topological Sorting and Strongly Connected
Components

Check for balanced parentheses in an expression


Given an expression string exp, examine whether the pairs and the orders of {,},
(,),[,] are correct in exp.
Example:
Input: exp = “[()]{}{[()()]()}”
Output: Balanced
Input: exp = “[(])”
Output: Not Balanced

Algorithm:
 Declare a character stack S.
 Now traverse the expression string exp.
1. If the current character is a starting bracket (‘(‘ or ‘{‘ or ‘[‘) then push it
to stack.
2. If the current character is a closing bracket (‘)’ or ‘}’ or ‘]’) then pop
from stack and if the popped character is the matching starting bracket
then fine else parenthesis are not balanced.
 After complete traversal, if there is some starting bracket left in stack then
“not balanced”
Infix to Postfix /Prefix conversion

Infix expression:The expression of the form a op b. When an operator is in-


between every pair of operands.
Postfix expression:The expression of the form a b op. When an operator is
followed for every pair of operands.
Why postfix representation of the expression?
Infix Expressions are harder for Computers to evaluate because of the additional
work needed to decide precedence.
The compiler scans the expression either from left to right or from right to left.
Consider the below expression: a op1 b op2 c op3 d
If op1 = +, op2 = *, op3 = +
The compiler first scans the expression to evaluate the expression b * c, then
again scan the expression to add a to it. The result is then added to d after
another scan.
The repeated scanning makes it very in-efficient. It is better to convert the
expression to postfix(or prefix) form before evaluation.
The corresponding expression in postfix form is: abc*+d+. The postfix
expressions can be evaluated easily using a stack. We will cover postfix
expression evaluation in a separate post.
Algorithm
1. Scan the infix expression from left to right.
2. If the scanned character is an operand, output it.
3. Else,
…..3.1 If the precedence of the scanned operator is greater than the precedence
of the operator in the stack(or the stack is empty or the stack contains a ‘(‘ ),
push it.
…..3.2 Else, Pop all the operators from the stack which are greater than or equal
to in precedence than that of the scanned operator. After doing that Push the
scanned operator to the stack. (If you encounter parenthesis while popping then
stop there and push the scanned operator in the stack.)
4. If the scanned character is an ‘(‘, push it to the stack.
5. If the scanned character is an ‘)’, pop the stack and and output it until a ‘(‘ is
encountered, and discard both the parenthesis.
6. Repeat steps 2-6 until infix expression is scanned.
7. Print the output
8. Pop and output from the stack until it is not empty.

Postfix Expression Evaluation


The Postfix notation is used to represent algebraic expressions. The expressions
written in postfix form are evaluated faster compared to infix notation as
parenthesis are not required in postfix.
Following is algorithm for evaluation postfix expressions.
1) Create a stack to store operands (or values).
2) Scan the given expression and do following for every scanned element.
a) If the element is a number, push it into the stack
b) If the element is a operator, pop operands for the operator from stack.
Evaluate the operator and push the result back to the stack
3) When the expression is ended, the number in the stack is the final
answer
Queue

A queue is a useful data structure in programming. It is similar to the ticket


queue outside a cinema hall, where the first person entering the queue is the first
person who gets the ticket.
Queue follows the First In First Out(FIFO) rule - the item that goes in first is the
item that comes out first too.

In the above image, since 1 was kept in the queue before 2, it was the first to be
removed from the queue as well. It follows the FIFO rule.
In programming terms, putting an item in the queue is called an "enqueue" and
removing an item from the queue is called "dequeue".
We can implement queue in any programming language like C, C++, Java,
Python or C#, but the specification is pretty much the same.

Queue Specifications
A queue is an object or more specifically an abstract data structure(ADT) that
allows the following operations:
• Enqueue: Add element to end of queue
• Dequeue: Remove element from front of queue
• IsEmpty: Check if queue is empty
• IsFull: Check if queue is full
• Peek: Get the value of the front of queue without removing it

How Queue Works


Queue operations work as follows:
1. Two pointers called FRONT and REAR are used to keep track of the first
and last elements in the queue.
2. When initializing the queue, we set the value of FRONT and REAR to -1.
3. On enqueing an element, we increase the value of REAR index and place
the new element in the position pointed to by REAR.
4. On dequeueing an element, we return the value pointed to by FRONT and
increase the FRONT index.
5. Before enqueing, we check if queue is already full.
6. Before dequeuing, we check if queue is already empty.
7. When enqueing the first element, we set the value of FRONT to 0.
8. When dequeing the last element, we reset the values of FRONT and
REAR to -1.
Queue Implementation in programming language
The most common queue implementation is using arrays, but it can also be
implemented using lists.
Implementation using C programming
1. #include<stdio.h>
2. #define SIZE 5
3.
4. void enQueue(int);
5. void deQueue();
6. void display();
7.
8. int items[SIZE], front = -1, rear = -1;
9.
10. int main()
11. {
12. //deQueue is not possible on empty queue
13. deQueue();
14.
15. //enQueue 5 elements
16. enQueue(1);
17. enQueue(2);
18. enQueue(3);
19. enQueue(4);
20. enQueue(5);
21.
22. //6th element can't be added to queue because queue is full
23. enQueue(6);
24.
25. display();
26.
27. //deQueue removes element entered first i.e. 1
28. deQueue();
29.
30. //Now we have just 4 elements
31. display();
32.
33. return 0;
34.
35. }
36.
37. void enQueue(int value){
38. if(rear == SIZE-1)
39. printf("\nQueue is Full!!");
40. else {
41. if(front == -1)
42. front = 0;
43. rear++;
44. items[rear] = value;
45. printf("\nInserted -> %d", value);
46. }
47. }
48.
49. void deQueue(){
50. if(front == -1)
51. printf("\nQueue is Empty!!");
52. else{
53. printf("\nDeleted : %d", items[front]);
54. front++;
55. if(front > rear)
56. front = rear = -1;
57. }
58. }
59.
60. void display(){
61. if(rear == -1)
62. printf("\nQueue is Empty!!!");
63. else{
64. int i;
65. printf("\nQueue elements are:\n");
66. for(i=front; i<=rear; i++)
67. printf("%d\t",items[i]);
68. }
69. }
When you run this program, you get the output
Queue is Empty!!
Inserted -> 1
Inserted -> 2
Inserted -> 3
Inserted -> 4
Inserted -> 5
Queue is Full!!
Queue elements are:
1 2 3 4 5
Deleted : 1
Queue elements are:
2 3 4 5

1. write a c program to implement queue using single linked list and perform
the operations i) enqueue ii) dequeue iii) display

Test case 1:
Enter no.of students
3
Enter id name marks
534 venkat 590
Enter id name marks
512 gnanesh 460
Enter id name marks
561 sudha 420
data in queue
534 venkat 590
512 gnanesh 460
561 sudha 420
after removing the front node
512 gnanesh 460
561 sudha 420

Test case 2:
input=
Enter no.of students
5
Enter id name marks
111 gopal 360
Enter id name marks
130 pawan 600
Enter id name marks
191 mahesh 240
Enter id name marks
244 suresh 610
Enter id name marks
275 akhil 401
data in queue
111 gopal 360
130 pawan 600
191 mahesh 240
244 suresh 610
275 akhil 401
after removing the front node
130 pawan 600
191 mahesh 240
244 suresh 610
275 akhil 401
*/

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct queue {
int sno;
char sname[20];
int tmarks;
struct queue* next;
};
struct queue* front=NULL;
struct queue* rear=NULL;
void enqueue(int no,char name[],int marks){
struct queue* temp=(struct queue*)malloc(sizeof(struct queue));
temp->sno=no;
strcpy(temp->sname,name);
temp->tmarks=marks;
temp->next=NULL;
if(front==NULL){
front=rear=temp;
}
else{
rear->next=temp;
rear=temp;
}
}
void dequeue(){
struct queue* dtemp=front;
if(front==NULL){
printf("queue is empty\n");
}
else{
front=front->next;
free(dtemp);
}
}
void display(){
struct queue* disp=front;
if(front==NULL){
printf("queue is empty\n");
}
else{

while(disp!=NULL){
printf("%d %s %d\n",disp->sno,disp->sname,disp->tmarks);
disp=disp->next;
}
}
}
int main(){
int i,n,id,marks;
char sname[10];
printf("Enter no.of students\n");
scanf("%d",&n);
for(i=0;i<n;i++){
printf("Enter id name marks\n");
scanf("%d %s %d",&id,sname,&marks);
enqueue(id,sname,marks);
}
printf("data in queue\n");
display();
dequeue();
printf("after removing the front node\n");
display();
}
Limitation of this implementation
As you can see in the image below, after a bit of enqueueing and dequeueing,
the size of the queue has been reduced.

The indexes 0 and 1 can only be used after the queue is reset when all the
elements have been dequeued.

By tweaking the code for queue, we can use the space by implementing a
modified queue called circular queue.

You might also like