UNIT II Data Structures OU
UNIT II Data Structures OU
Linked Lists ADT: Singly linked lists: Representation in memory, Algorithms of several
operations: Traversing, Searching, Insertion into, Deletion from linked list; Linked
representation of Stack and Queue
Doubly linked list: Operations like traversing, searching, insertion, deletion, Circular
Linked Lists: operations like traversing, searching, insertion, deletion.
2. LINKED LISTS
Linked lists and arrays are similar since they both store collections of data. Linked lists have
their own strengths and weaknesses, but they happen to be strong where arrays are weak.
Generally array's allocates the memory for all its elements in one block whereas linked lists
use an entirely different strategy. Linked lists allocate memory for each element separately
and only when necessary.
2.1. Linked List Concepts:
A linked list is a non-sequential collection of data items. It is a dynamic data structure. For
every data item in a linked list, there is an associated pointer that would give the memory
location of the next data item in the linked list. The data items in the linked list are not in
consecutive memory locations. They may be anywhere, but the accessing of these data items
is easier as each data item contains the address of the next data item.
Advantages of linked lists:
Linked lists have many advantages. Some of the very important advantages are:
• Linked lists are dynamic data structures. i.e., they can grow or shrink during the
execution of a program.
• Linked lists have efficient memory utilization. Here, memory is not preallocated.
Memory is allocated whenever it is required and it is de-allocated (removed) when it
is no longer needed.
• Insertion and Deletions are easier and efficient. Linked lists provide flexibility in
inserting a data item at a specified position and deletion of the data item from the
given position.
• Many complex applications can be easily carried out with linked lists.
Disadvantages of linked lists:
1) It consumes more space because every node requires an additional pointer to store
address of the next node.
2) Searching a particular element in list is difficult and time consuming.
2.2. Types of Linked Lists:
Basically we can put linked lists into the following four items:
1) Single Linked List
2) Double Linked List
3) Circular Linked List.
4) Circular Double Linked List.
1
A single linked list is one in which all nodes are linked together in some sequential manner.
Hence, it is also called as linear linked list.
A double linked list is one in which all nodes are linked together by multiple links which
helps in accessing both the successor node (next node) and predecessor node (previous node)
from any arbitrary node within the list. Therefore each node in a double linked list has two
link fields (pointers) to point to the left node (previous) and the right node (next). This helps
to traverse in forward direction and backward direction.
A circular linked list is one, which has no beginning and no end. A single linked list can be
made a circular linked list by simply storing address of the very first node in the link field of
the last node.
A circular double linked list is one, which has both the successor pointer and predecessor
pointer in the circular manner.
Comparison between array and linked list
2
A linked list allocates space for each element separately in its own block of memory called a
"node". The list gets an overall structure by using pointers to connect all its nodes together
like the links in a chain. Each node contains two fields; a "data" field to store whatever
element, and a "next" field which is a pointer used to link to the next node. Each node is
allocated in the heap using malloc(), so the node memory continues to exist until it is
explicitly de-allocated using free(). The front of the list is a pointer to the “start” node.
A single linked list is shown in figure 3.2.1.
The beginning of the linked list is stored in a "start" pointer which points to the first node.
The first node contains a pointer to the second node. The second node contains a pointer to
the third node, ... and so on. The last node in the list has its next field set to NULL to mark
the end of the list.
2.3.2 Implementation of Single Linked List:
Before writing the code to build the above list, we need to create a start node, used to create
and access other nodes in the linked list. The following structure definition will do (see figure
3.2.2):
• Creating a structure with one data item and a next pointer, which will be pointing to
next node of the list. This is called as self-referential structure.
• Initialise the start pointer to be NULL
3
• Deletion.
• Traversing.
2.3.3 Creating a node for Single Linked List:
Creating a singly linked list starts with creating a node. Sufficient memory has to be allocated
for creating a node. The information is stored in the memory, allocated by using the malloc()
function. The function getnode(), is used for creating a node, after allocating memory for the
structure of type node, the information for the item (i.e., data) has to be read from the user,
set next field to NULL and finally returns the address of the node.
Figure 3.2.3 illustrates the creation of a node for single linked list.
4
Insertion of a Node:
One of the most primitive operations that can be done in a singly linked list is the insertion of
a node. Memory is to be allocated for the new node (in a similar way that is done while
creating a list) before reading the data. The new node will contain empty data field and empty
next field. The data field of the new node is then stored with the information read from the
user. The next field of the new node is assigned to NULL. The new node can then be inserted
at three different places namely:
• Inserting a node at the beginning.
• Inserting a node at the end.
• Inserting a node at intermediate position.
2.3.5 Inserting a node at the beginning:
The following steps are to be followed to insert a new node at the beginning of the list:
• Get the new node using getnode().
newnode = getnode();
• If the list is empty then start = newnode.
• If the list is not empty, follow the steps given below:
newnode -> next = start;
start = newnode;
5
The function insert_at_beg(), is used for inserting a node at the beginning
void insert_at_beg()
{
node *newnode;
newnode = getnode();
if(start == NULL)
{
start = newnode;
}
else
{
newnode -> next = start;
start = newnode;
}
}
2.3.6 Inserting a node at the end:
The following steps are followed to insert a new node at the end of the list:
• Get the new node using getnode()
newnode = getnode();
• If the list is empty then start = newnode.
• If the list is not empty follow the steps given below:
temp = start;
while(temp -> next != NULL)
temp = temp -> next;
temp -> next = newnode
6
The function insert_at_end(), is used for inserting a node at the end.
void insert_at_end()
{
node *newnode, *temp;
newnode = getnode();
if(start == NULL)
{
start = newnode;
}
else
{
temp = start;
while(temp -> next != NULL)
temp = temp -> next;
temp -> next = newnode;
}
}
2.3.7 Inserting a node at intermediate position:
The following steps are followed, to insert a new node in an intermediate position in the list:
• Get the new node using getnode().
newnode = getnode();
• Ensure that the specified position is in between first node and last node. If not,
specified position is invalid. This is done by countnode() function.
• Store the starting address (which is in start pointer) in temp and prev pointers. Then
traverse the temp pointer upto the specified position followed by prev pointer.
• After reaching the specified position, follow the steps given below:
prev -> next = newnode;
newnode -> next = temp;
• Let the intermediate position be 3.
7
Figure 3.2.7 shows inserting a node into the single linked list at a specified intermediate
position other than beginning and end.
The function insert_at_mid(), is used for inserting a node in the intermediate position.
void insert_at_mid()
{
node *newnode, *temp, *prev;
int pos, nodectr, ctr = 1;
newnode = getnode();
printf("\n Enter the position: ");
scanf("%d", &pos);
nodectr = countnode(start);
if(pos > 1 && pos < nodectr)
{
temp = prev = start;
while(ctr < pos)
{
prev = temp;
temp = temp -> next;
ctr++;
}
prev -> next = newnode;
newnode -> next = temp;
}
else
{
printf("position %d is not a middle position", pos);
}
}
Deletion of a node:
Another primitive operation that can be done in a singly linked list is the deletion of a node.
Memory is to be released for the node to be deleted. A node can be deleted from the list from
three different places namely.
• Deleting a node at the beginning.
8
• Deleting a node at the end.
• Deleting a node at intermediate position.
2.3.8 Deleting a node at the beginning:
The following steps are followed, to delete a node at the beginning of the list:
• If list is empty then display ‘Empty List’ message.
• If the list is not empty, follow the steps given below:
temp = start;
start = start -> next;
free(temp);
Figure 3.2.8 shows deleting a node at the beginning of a single linked list.
The function delete_at_beg(), is used for deleting the first node in the list.
void delete_at_beg()
{
node *temp;
if(start == NULL)
{
printf("\n No nodes are exist..");
return ;
}
else
{
temp = start;
start = temp -> next;
free(temp);
printf("\n Node deleted ");
}
}
9
prev = temp;
temp = temp -> next;
}
prev -> next = NULL;
free(temp);
The function delete_at_last(), is used for deleting the last node in the list.
void delete_at_last()
{
node *temp, *prev;
if(start == NULL)
{
printf("\n Empty List..");
return ;
}
else
{
temp = start;
prev = start;
while(temp -> next != NULL)
{
prev = temp;
temp = temp -> next;
}
prev -> next = NULL;
free(temp);
printf("\n Node deleted ");
}
}
2.3.10 Deleting a node at Intermediate position:
The following steps are followed, to delete a node from an intermediate position in the list
(List must contain more than two node).
• If list is empty then display ‘Empty List’ message
• If the list is not empty, follow the steps given below.
if(pos > 1 && pos < nodectr)
{
temp = prev = start;
10
ctr = 1;
while(ctr < pos)
{
prev = temp;
temp = temp -> next;
ctr++;
}
prev -> next = temp -> next;
free(temp);
printf("\n node deleted..");
}
The function delete_at_mid(), is used for deleting the intermediate node in the list.
void delete_at_mid()
{
int ctr = 1, pos, nodectr;
node *temp, *prev;
if(start == NULL)
{
printf("\n Empty List..");
return ;
}
else
{
printf("\n Enter position of node to delete: ");
scanf("%d", &pos);
nodectr = countnode(start);
if(pos > nodectr)
{
printf("\nThis node doesnot exist");
if(pos > 1 && pos < nodectr)
{
temp = prev = start;
while(ctr < pos)
{
prev = temp;
temp = temp -> next;
11
ctr ++;
}
prev -> next = temp -> next;
free(temp);
printf("\n Node deleted..");
}
else
{
printf("\n Invalid position..");
getch();
}
}
}
12
2.4 Array representation of Linked List
Array based linked lists: Another alternative is to allocate the nodes in blocks. In fact, if you
know the maximum size of a list a head of time, you can pre-allocate the nodes in a single
array. The result is a hybrid structure – an array based linked list.
Figure 3.5.1 shows an example of null terminated single linked list where all the nodes are
allocated contiguously in an array.
13
2.5.1 Creating a circular single Linked List with ‘n’ number of nodes:
The following steps are to be followed to create ‘n’ number of nodes:
• Get the new node using getnode().
newnode = getnode();
• If the list is empty, assign new node as start.
start = newnode;
• If the list is not empty, follow the steps given below:
temp = start;
while(temp -> next != NULL)
temp = temp -> next;
temp -> next = newnode;
• Repeat the above steps ‘n’ times.
newnode -> next = start;
2.5.2 Inserting a node at the beginning:
The following steps are to be followed to insert a new node at the beginning of the
circular list:
• Get the new node using getnode().
newnode = getnode();
• If the list is empty, assign new node as start.
start = newnode;
newnode -> next = start;
• If the list is not empty, follow the steps given below:
last = start;
while(last -> next != start)
last = last -> next;
newnode -> next = start;
start = newnode;
last -> next = start;
Figure 3.6.2 shows inserting a node into the circular single linked list at the beginning
14
2.5.3 Inserting a node at the end:
The following steps are followed to insert a new node at the end of the list:
• Get the new node using getnode().
newnode = getnode();
• If the list is empty, assign new node as start.
start = newnode;
newnode -> next = start;
• If the list is not empty follow the steps given below:
temp = start;
while(temp -> next != start)
temp = temp -> next;
temp -> next = newnode;
newnode -> next = start;
15
2.5.5 Deleting a node at the end:
The following steps are followed to delete a node at the end of the list:
• If the list is empty, display a message ‘Empty List’.
• If the list is not empty, follow the steps given below:
temp = start;
prev = start;
while(temp -> next != start)
{
prev = temp;
temp = temp -> next;
}
prev -> next = start;
• After deleting the node, if the list is empty then start = NULL.
Figure 3.6.5 shows deleting a node at the end of a circular single linked list.
16
Many applications require searching forward and backward thru nodes of a list. For example
searching for a name in a telephone directory would need forward and backward scanning
thru a region of the whole list.
The basic operations in a double linked list are:
• Creation.
• Insertion.
• Deletion.
• Traversing.
The beginning of the double linked list is stored in a "start" pointer which points to the first
node. The first node’s left link and last node’s right link is set to NULL.
17
2.6.2 Creating a Double Linked List with ‘n’ number of nodes:
The following steps are to be followed to create ‘n’ number of nodes:
• Get the new node using getnode().
newnode =getnode();
• If the list is empty then start = newnode.
• If the list is not empty, follow the steps given below:
• The left field of the new node is made to point the previous node.
• The previous nodes right field must be assigned with address of the new node.
• Repeat the above steps ‘n’ times.
The function createlist(), is used to create ‘n’ number of nodes:
Figure 3.4.3 shows 3 items in a double linked list stored at different locations.
18
The function dbl_insert_beg(), is used for inserting a node at the beginning. Figure 3.4.4
shows inserting a node into the double linked list at the beginning.
19
• After reaching the specified position, follow the steps given below:
newnode -> left = temp;
newnode -> right = temp -> right;
temp -> right -> left = newnode;
temp -> right = newnode;
The function dbl_insert_mid(), is used for inserting a node in the intermediate position.
Figure 3.4.6 shows inserting a node into the double linked list at a specified intermediate
position other than beginning and end.
20
The function dbl_delete_last(), is used for deleting the last node in the list. Figure 3.4.7
shows deleting a node at the end of a double linked list.
21
2.6.9 Traversal and displaying a list (Left to Right):
To display the information, you have to traverse the list, node by node from the first node,
until the end of the list is reached. The function traverse_left_right() is used for traversing and
displaying the information stored in the list from left to right.
The following steps are followed, to traverse a list from left to right:
• If list is empty then display ‘Empty List’ message.
• If the list is not empty, follow the steps given below:
temp = start;
while(temp != NULL)
{
print temp-> data;
temp = temp -> right;
}
22
The basic operations in a circular double linked list are:
• Creation.
• Insertion.
• Deletion.
• Traversing
Creating a Circular Double Linked List with ‘n’ number of nodes:
The following steps are to be followed to create ‘n’ number of nodes:
• Get the new node using getnode().
newnode = getnode();
• If the list is empty, then do the following
start = newnode;
newnode -> left = start;
newnode ->right = start;
• If the list is not empty, follow the steps given below:
newnode -> left = start -> left;
newnode -> right = start;
start -> left->right = newnode;
start -> left = newnode;
• Repeat the above steps ‘n’ times.
The function cdll_createlist(), is used to create ‘n’ number of nodes:
2.7.1 Inserting a node at the beginning:
The following steps are to be followed to insert a new node at the beginning of the list:
• Get the new node using getnode().
newnode=getnode();
• If the list is empty, then
start = newnode;
newnode -> left = start;
newnode -> right = start;
• If the list is not empty, follow the steps given below:
newnode -> left = start -> left;
newnode -> right = start;
start -> left -> right = newnode;
start -> left = newnode;
start = newnode;
The function cdll_insert_beg(), is used for inserting a node at the beginning. Figure 3.8.2
shows inserting a node into the circular double linked list at the beginning.
23
2.7.2 Inserting a node at the end:
The following steps are followed to insert a new node at the end of the list:
• Get the new node using getnode()
newnode=getnode();
• If the list is empty, then
start = newnode;
newnode -> left = start;
newnode -> right = start;
• If the list is not empty follow the steps given below:
newnode -> left = start -> left;
newnode -> right = start;
start -> left -> right = newnode;
start -> left = newnode;
The function cdll_insert_end(), is used for inserting a node at the end. Figure 3.8.3 shows
inserting a node into the circular linked list at the end.
24
• After reaching the specified position, follow the steps given below:
newnode -> left = temp;
newnode -> right = temp -> right;
temp -> right -> left = newnode;
temp -> right = newnode;
nodectr++;
The function cdll_insert_mid(), is used for inserting a node in the intermediate position.
Figure 3.8.4 shows inserting a node into the circular double linked list at a specified
intermediate position other than beginning and end.
The function cdll_delete_beg(), is used for deleting the first node in the list. Figure 3.8.5
shows deleting a node at the beginning of a circular double linked list.
25
temp = start;
while(temp -> right != start)
{
temp = temp -> right;
}
temp -> left -> right = temp -> right;
temp -> right -> left = temp -> left;
The function cdll_delete_last(), is used for deleting the last node in the list. Figure 3.8.6
shows deleting a node at the end of a circular double linked list.
26
2.7.7 Traversing a circular double linked list from left to right:
The following steps are followed, to traverse a list from left to right:
• If list is empty then display ‘Empty List’ message.
• If the list is not empty, follow the steps given below:
temp = start;
Print temp -> data;
temp = temp -> right;
while(temp != start)
{
print temp-> data;
temp = temp -> right;
}
The function cdll_display_left _right(), is used for traversing from left to right.
2.7.8 Traversing a circular double linked list from right to left:
The following steps are followed, to traverse a list from right to left:
• If list is empty then display ‘Empty List’ message.
• If the list is not empty, follow the steps given below:
temp = start;
do
{
temp = temp -> left;
print temp -> data;
} while(temp != start);
The function cdll_display_right_left(), is used for traversing from right to left.
27
IMPORTANT QUESTIONS
28