Linked List implementation in C language

Get FREE domain for 1st year and build your brand new site

Binary Tree Problems books

A linked list is a linear data structure. It is defines as the collection of objects called nodes that are randomly stored in memory. These nodes are connected together via links.

  • A node contains two fields:
    -Data part: This part of the node holds the value/element.
    -Link part: This part of the node holds the address of the next node.
  • The last node of the linked list contains pointer to the null/end of list.

In this article, we have designed and implemented Linked List in C Programming Language. We have create a Node structure in C and implemented all Linked List operations in C.

Structure of a node

As we know that a node contains data part and link part. So we will create a structure using struct keyword.

struct node
{
    int data;
    struct node*next;
};
struct node *start, *p;
p=(struct node*)malloc(sizeof(struct node));

Here, we've created a structure of a node.
int data is the data part of the node which will hold the data.
struct node * next is the pointer variable of node datatype.
struct node * start defines start as a variable which can store the address of the node.
p is a pointer variable which is used to create memory block in RAM.

Advantages of linked list

  • Linked list is a dynamic data structure so it can grow or shrink during runtime by allocating and deallocating memory.
  • As the memory is allocated or deallocated during runtime so there is no memory wastage.
  • The operations like insertion, deletion of nodes are easy as compared to that of array.
  • Data structures such as stack, queue can be implemented easily.

Disadvantages of linked list

  • Traversal is difficult in linked list. If we want to access any node randomly, then we have to traverse all the nodes before it.
  • It uses more memory because each node contains a pointer and it requires extra memory for itself.

Types of linked list

There are three types of linked list:
-Singly Linked list.
-Doubly linked list.
-Circular Linked list.

Singly linked list

Singly Linked list is also known as one way list list in which we can traverse only in forward/one direction because a node in singly linked list contains a data part and a link part.
The data part of the node holds the value/element and link part of the node holds the address of its immediate successor.

Operations on Singly linked list

1. Insertion:

The insertion operation in linked list is used to insert the new node. The insertion of node in singly linked list can be performed at different positions.

a) Insertion of node in the beginning:

In this a new node is inserted in the front of already existing linked list. For this we have to follow some steps:

  • First we will create a new node and store the data into the data part.
  • Now we will point the link part of the new node with the first node(start) of existing linked list
  • After that we will make new node as the first node(start)
p=(struct node *) malloc(sizeof(struct node));  
p→data=value; 
p->next=start;
start=p;     //new node 'p' will become the first node of the list

b) Insertion of node at the end:

The insertion of node at the end of singly linked list can have two cases:

  • First case when there is not even a single node in the list(list is empty). In this case the condition (start==NULL) will be satisfied.
    Since, 'p' is the only node that will be inserted in the list so we need to make this node point to the 'start' pointer.
p->data=value;  
  p->next=NULL;
  start=p;
  • Second case when we have to add a node at the end of already existing linked list. In this we will use a loop to traverse to the end of list. So, we need to declare a temporary variable temp in order to traverse through the list.
  • At the end of the loop, the temp will be point to the last node of the list. The next part of the temp node will point to the new node 'p'. The next part of node 'p' will point to the null.
temp=start;
while(temp→next!=NULL)  //traverse through the list
    temp=temp→next;
    
temp=start;  
while(temp->next!=NULL)    
    temp=temp->next;  
temp->next=p;       //next of temp will point to 'p'
p->next=NULL;       //next of 'p' will point to null

C) Inserting a node at any specified location:

  • In this operation, we will skip some nodes until we reach the specified location. Once we reach the location, we will insert the node there. Here, we will use a for loop to reach the location where we want to insert our new node.
for(i=0;i<loc;i++)  //loc represents the location where we want to insert the node
{  
    temp=temp->next;  
    if(temp==NULL) 
        return; 
}  
  • Create a new node 'p store the data in the data part.
  • The next part of the new node p must contain the address part of the next part of the temp
  • Last step would be to make the next part of the temp point to the new node p.
p=(struct node*)malloc(sizeof(struct node));
p->data=value;
p->next=temp->next;
temp->next=p;

2. Deletion:

The deletion operation in linked list is used to delete the node. Just like insertion, the deletion operation on linked list can be performed at different positions.

a) Deletion of node in the beginning:

  • Deletion of a node in the beginning is a simple operation. Here, we will first copy the address of the first node 'start' to some temporary variable say 'p'.
  • Move the first node 'start' to the second node of the linked list i.e.start =start->next.
  • Now, free the pointer p.
    The free() function is used to de-allocate the memory.
p=start;  
start=start->next;
free(p);

b) Deletion of node at the end of linked list:

There can be two cases while implementing deletion operation at the end of a singly linked list.

  • First case: if there is only one node in the list,then the condition (start==NULL) will be satisfied and the start node will be assigned to null.
p=start;  
  start=NULL;  
  free(p);    //'p' will be deleted
  • Second case: Here we have to traverese the list until we reach the end node of the list. The temp pointer is assigned to start pointer of the list and it will traverse the list till it reaches to the last node.
p=start;   
  while(p->next!=NULL)  
  {  
  p1=p;    //'p1' keeps track of second last node.
  p=p->next;  
  } 
  p1->next=NULL;  
  free(p);

c) Deletion of node at any specified position:

  • When we performed insertion operation of node at specified location, we skipped the nodes until we reached the desired location. Similarly, in the deletion operation of node at specified location we will skip some nodes until we reach the specified location.
  • Here, we need to keep track of two nodes. One which is to be deleted 'p' and the other which is just before that node 'p1'.
p=start;  
for(i=0;i<loc;i++)  
{  
    p1=p;       
    p=p->next;  
if(p==NULL)  //when the location entered is more than the size of linked list
{  
    printf("\nlocation does not exist");  
    return;  
}  
}  

Now,we just have to make some pointer adjustments. The next of p1 will point to the next of p.

p1->next=p->next;
free(p);   //'p' will be deleted

3. Traversing

Traversing operation is the most commonly performed operation in singly linked list. Traversing means visiting each node of the linked list at least once in order to perform some operation. Example: printing the elements in the linked list.

p=start;   
while (p!=NULL)   
    p=p->next;  

So these were some operations that we can perform on singly linked list.

A complete program of different types of operations on singly linked list

#include<stdio.h>  
#include<stdlib.h>  
struct node   
{  
    int data;  
    struct node *next;   
};  
struct node *start;  
               /*fuction declaration of all the operations*/
void insert_begin();   
void insert_last();  
void insert_locc();  
void delete_begin();  
void delete_last();  
void delete_locc();  
void print();  
void main ()  
{  
    int ch=0;  
    while(ch!=8)   
    {    
        printf("\nEnter the operation to be performed\n");    
        printf("\n1.Insert in the begining\n2.Insert at last\n3.Insert at any specified position\n4.Delete from Beginning\n5.Delete from last\n6.Delete node after specified location\n7.Show\n8.Exit\n");           
        scanf("\n%d",&ch);  
        switch(ch)  
        {        /*function calls of all the operations */
            case 1:  
            insert_begin();       
            break;  
            case 2:  
            insert_last();         
            break;  
            case 3:  
            insert_locc();       
            break;  
            case 4:  
            delete_begin();       
            break;  
            case 5:  
            delete_last();        
            break;  
            case 6:  
            delete_locc();           
            break;  
            case 7:  
            print();        
            break;  
            case 8:  
            exit(0);  
            break;  
            default:  
            printf("Enter valid option");  
        }  
    }  
}           /*function definition*/
void insert_begin()                  //to insert the node at the beginnning of linked list
{  
    struct node *p;  
    int value;  
    p=(struct node *) malloc(sizeof(struct node *));  
    if(p==NULL)  
    {  
        printf("\nOVERFLOW");  
    }  
    else  
    {  
        printf("\nEnter value\n");    
        scanf("%d",&value);    
        p->data=value;  
        p->next=start;  
        start=p;  
    }  
}  
void insert_last()                //to insert the node at the last of linked list
{  
    struct node *p,*temp;  
    int value;     
    p=(struct node*)malloc(sizeof(struct node));      
    if(p==NULL)  
    {  
        printf("\nOVERFLOW");     
    }  
    else  
    {  
        printf("\nEnter value\n");  
        scanf("%d",&value);  
        p->data=value;  
        if(start==NULL)  
        {  
            p->next=NULL;  
            start=p;  
        }  
        else  
        {  
            temp=start;  
            while(temp->next!=NULL)  
            {  
                temp=temp->next;  
            }  
            temp->next=p;  
            p->next=NULL;  
        }  
    }  
}  
void insert_locc()               //to insert the node at the specified location of linked list
{  
    int i,loc,value;   
    struct node *p, *temp;  
    p=(struct node *)malloc(sizeof(struct node));  
    if(p==NULL)  
    {  
        printf("\nOVERFLOW");  
    }  
    else  
    {  
        printf("\nEnter element value");  
        scanf("%d",&value);  
        p->data=value;  
        printf("\nEnter the location after which you want to insert ");  
        scanf("\n%d",&loc);  
        temp=start;  
        for(i=0;i<loc;i++)  
        {  
            temp=temp->next;  
            if(temp==NULL)  
            {  
                printf("\ncan't insert\n");  
                return;  
            }  
        }  
        p->next=temp->next;   
        temp->next=p; 
    }  
}  
void delete_begin()          //to delete the node present in the beginning of the linked list
{  
    struct node *p;  
    if(start==NULL)  
    {  
        printf("\nList is empty\n");  
    }  
    else   
    {  
        p=start;  
        start=p->next;  
        free(p);  
    }  
}  
void delete_last()          //to delete the node present in the last of the linked list
{  
    struct node *p,*p1;  
    if(start==NULL)  
    {  
        printf("\nlist is empty");  
    }  
    else if(start->next==NULL)  
    {  
        start=NULL;  
        free(start);  
        printf("\nOnly node of the list deleted ...\n");  
    }  
    else  
    {  
        p=start;   
        while(p->next!=NULL)  
        {  
            p1=p;  
            p=p->next;  
        }  
        p1->next=NULL;  
        free(p);  
    }     
}  
void delete_locc()    //to delete the node present at the specified of the linked list
{  
    struct node *p,*p1;  
    int loc,i;    
    printf("\n Enter the location of the node after which you want to perform deletion \n");  
    scanf("%d",&loc);  
    p=start;  
    for(i=0;i<loc;i++)  
    {  
        p1=p;       
        p=p->next;  
           
        if(p==NULL)  
        {  
            printf("\nCan't delete");  
            return;  
        }  
    }  
    p1->next=p->next;  
    free(p);  
    printf("\nDeleted node %d ",loc+1);  
}  
void print()    //to print the values in the linked list
{  
    struct node *p;  
    p=start;   
    if(p==NULL)  
    {  
        printf("Nothing to print");  
    }  
    else  
    {  
        printf("\nprinting values\n");   
        while (p!=NULL)  
        {  
            printf("\n%d",p->data);  
            p=p->next;  
        }  
    }  
}     

OUTPUT:

Enter the operation to be performed

1.Insert in begining
2.Insert at last
3.Insert at any specified position
4.Delete from Beginning
5.Delete from last
6.Delete node after specified location
7.Show
8.Exit
1

Enter value
89

Enter the operation to be performed

1.Insert in begining
2.Insert at last
3.Insert at any specified position
4.Delete from Beginning
5.Delete from last
6.Delete node after specified location
7.Show
8.Exit
1

Enter value
44

Enter the operation to be performed

1.Insert in begining
2.Insert at last
3.Insert at any specified position
4.Delete from Beginning
5.Delete from last
6.Delete node after specified location
7.Show
8.Exit
1

Enter value
78

Enter the operation to be performed

1.Insert in begining
2.Insert at last
3.Insert at any specified position
4.Delete from Beginning
5.Delete from last
6.Delete node after specified location
7.Show
8.Exit
2

Enter value
80

Enter the operation to be performed

1.Insert in begining
2.Insert at last
3.Insert at any specified position
4.Delete from Beginning
5.Delete from last
6.Delete node after specified location
7.Show
8.Exit
7

printing values

78
44
89
80
Enter the operation to be performed

1.Insert in begining
2.Insert at last
3.Insert at any specified position
4.Delete from Beginning
5.Delete from last
6.Delete node after specified location
7.Show
8.Exit
5

Enter the operation to be performed

1.Insert in begining
2.Insert at last
3.Insert at any specified position
4.Delete from Beginning
5.Delete from last
6.Delete node after specified location
7.Show
8.Exit
7

printing values 

78
44
89
Enter the operation to be performed

1.Insert in begining
2.Insert at last
3.Insert at any specified position
4.Delete from Beginning
5.Delete from last
6.Delete node after specified location
7.Show
8.Exit

Doubly linked List

Doubly linked list is also a sequence of nodes in which a single node contains three fields. In doubly linked list there are two link fields and one data field.
The first link is the pointer to the previous node of the doubly linked list and the second link is the pointer to the next node of the doubly linked list.

Structure of a node in doubly linked list

struct node   
{  
    struct node *prev;   //pointer to the previous node
    int data;            //holds the data 
    struct node *next;   //pointer to the next node
}

Operations on a doubly linked list

1. Insertion:

The insertion operation in linked list is used to insert the new node. The insertion of node in doubly linked list can be performed at different positions.I doubly linked list we have two pointers to maintain as compared to singly linked list

a) Insertion of node in the beginning:

There are two cases while inserting a new node in the beginning of the doubly linked list. Either the list is empty or there is at least one node in the linked list.

  • First we will create a new node
    p=(struct node*)malloc(sizeof(struct node));
  • In the next step we will check we will work on the first case(when the list is empty). The list is empty if the condition (start==NULL) is accepted.In this case the node will be inserted as the only node.So,the 'prev' and the 'next' pointer of the node will point to 'NULL' and the 'start' pointer will point to node 'P'.
p->next=NULL;   //prevoius and next pointer will point to NULL
p->prev=NULL;  
p->data=value;     
start=p;           //'start' will point to the new node/inserted node 'p'
  • In the second case the condition (start==NULL) will not be satisfied.It means there is at least one node in the linked list. The 'next' pointer of the node 'p' will point to the 'start' pointer. The 'prev' pointer of the node 'start' will point to the new node 'p'.
p->next=start;  //the next pointer of the 'p' will point to the 'start' pointer
start→prev=p;     //the previous pointer of the 'start' will point to the new node/inserted node 'p'
p→prev=NULL;  
start=p;

b) Insertion of node in the end:

There are two cases while inserting a node at the last of the doubly linked list. Either the list is empty or there is at least one node in the linked list.

  • First we will create a new node
    p=(struct node*)malloc(sizeof(struct node));
  • First case(when the list is empty). The list is empty if the condition (start==NULL) is accepted.In this case the node will be inserted as the only node and therefore the 'prev' and the 'next' pointer of the node 'p' will point to NULL and the 'start' pointer will point to node 'p'.
p->next=NULL;   //next pointer pointing to NULL
p->prev=NULL;   //prev pointer pointing to NULL 
p->data=value;     
start=p;        //start will point to the new node/inserted node 'p'
  • In the second case the condition (start==NULL) will be false. It means there is at least one node in the linked list. Now, we will take a temporary variable which will traverse the list by using pointer.
temp=head;            
while(temp!=NULL)  
    temp=temp→next;     
temp->next=ptr;      //pointer of temp will point to the new node
ptr->prev=temp;      //previous pointer of new node(ptr) points to the last node(temp)
ptr->next=NULL;      //next pointer of new node(ptr) points to the NULL as it will be the last node of the list.

c) Insertion of node at any specified location of doubly linked list:

  • In this operation, we will skip some nodes untill we reach the specified location. Once we reach the location, we will insert the node there. Here, we will use a for loop to reach the location where we want to insert our new node.
  • First we will create a new node
    p=(struct node)malloc(sizeof(struct node));*
  • In this, we will also use a temporary pointer variable to traverse the list until we reach the specified location.
  • The 'temp' pointer will point to the specified node at the end of the loop.
temp=start;  
    for(i=0;i<loc;i++)    //will iterate until it reaches to specified location
   {  
       temp=temp->next;  
       if(temp==NULL) 
           return;
   } 
 p→next=temp→next;  //the next pointer of 'p' point to the next node of temp
 p→prev=temp;       //the prev of the new node 'p' point to temp
 temp→next=p;       //the next pointer of temp point to the new node 'p'
 temp→next→prev=p;  //the previous pointer of the next node of temp point to the new node'p'

2. Deletion:

The deletion operation in linked list is used to delete the node. Just like insertion, the deletion operation on doubly linked list can be performed at different positions.

a) Deletion of node in the beginning of doubly linked list:

  • Deletion of node at the beginning of doubly linked list can be done in few steps. First we will copy or store the 'start' pointer to pointer 'p' and shift the 'start' pointer to its next.
start=p;            //'p' is stored in 'start'
start=start->next;  //shift 'start' pointer to its next
start->prev=NULL;   //previous pointer of 'start' point to NULL
free(p);            //delete/free the pointer 'p' by using free() function

b) Deletion of node at the end of the doubly linked list:

  • There can be a possibility that the list is empty and no operation can be performed on it. So the condition (start==NULL) will be satisfied and no deletion operation is performed.
  • And if the list is not empty then we will traverse through the list till we reach the end of doubly linked list.
p=start;   
if(p->next!=NULL) 
    p=p->next;
p→prev→next=NULL;  //next of previous of p will point to NULL
free(p);           //delete/free the pointer p by using free() function

c) Deletion of node at the specified location of the doubly linked list:

  • In order to delete the node at any specified location in doubly linked list, first we will copy the start pointer to the temp pointer and then traverse the list until we get the specified/desired location.
temp=start;
while(temp->data!=val)  
temp=temp->next;
  • After this we will check whether the node which is to be deleted is the last node of the list, if it so then we have to make the next pointer of this node point to null so that it can be the new last node of the list.
  • If that is not satisfied then make the pointer 'p' point to the node which is to be deleted. Make the next of temp point to the next of node 'p'. Make the previous of next node of 'p' point to temp. free the node 'p'.
if(temp->next==NULL)   
    return;  //can't perform deletion 
if(temp->next->next==NULL)  
    temp->next=NULL; 
    
p=temp->next;  
        temp->next=p->next;  //next of temp will point to the next of 'p'
        p->next->prev=temp;  //previous of next of node 'p' will point to temp.
        free(p);             //delete/free the pointer 'p' by using free() function

3. Traversing

Traversing operation is the most commonly performed operation in doubly linked list. Traversing means visiting each node of the linked list at least once in order to perform some operation. Example: printing the elements in the linked list.
We will use a while loop for printing or traversing the list.

while(p!=NULL)  
{  
printf("%d\n",p->data);  
pr=p->next;  
}

A complete program of different types of operations on doubly linked list

#include<stdio.h>  
#include<stdlib.h>  
struct node  
{  
    struct node *prev;  
    struct node *next;  
    int data;  
};  
struct node *start;  
/*fuction declaration of all the operations*/
void insert_begin();   
void insert_last();  
void insert_locc();  
void delete_begin();  
void delete_last();  
void delete_locc();  
void print();  
void main ()  
{  
int ch=0;  
    while(ch!=8)  
    {  
        printf("\nEnter the operation to be performed\n");  
        printf("\n1.Insert in the begining\n2.Insert at last\n3.Insert at any specified position\n4.Delete from Beginning\n5.Delete from last\n6.Delete node after specified location\n7.Print\n8.Exit\n");  
        scanf("\n%d",&ch);  
        switch(ch)  
        {  
                 /*function calls of all the operations */
            case 1:  
            insert_begin();       
            break;  
            case 2:  
            insert_last();         
            break;  
            case 3:  
            insert_locc();       
            break;  
            case 4:  
            delete_begin();       
            break;  
            case 5:  
            delete_last();        
            break;  
            case 6:  
            delete_locc();           
            break;  
            case 7:  
            print();        
            break;  
            case 8:  
            exit(0);  
            break;  
            default:  
            printf("Enter valid option");
        }  
    }  
}  /*function deefinition*/
void insert_begin()      //to insert the node in the beginning 
{  
   struct node *p;   
   int value;  
   p=(struct node *)malloc(sizeof(struct node));  
   if(p==NULL)  
   {  
       printf("\nOVERFLOW");  
   }  
   else  
   {  
    printf("\nEnter value: ");  
    scanf("%d",&value);  
      
   if(start==NULL)  
   {  
       p->next=NULL;  
       p->prev=NULL;  
       p->data=value;  
       start=p;  
   }  
   else   
   {  
       p->data=value;  
       p->prev=NULL;  
       p->next=start;  
       start->prev=p;  
       start=p;  
   }  
}  
}  
void insert_last()            //to insert the node at the last of the list  
{  
   struct node *p,*temp;  
   int value;  
   p=(struct node *)malloc(sizeof(struct node));  
   if(p==NULL)  
   {  
       printf("\nOVERFLOW");  
   }  
   else  
   {  
       printf("\nEnter value: ");  
       scanf("%d",&value);  
        p->data=value;  
       if(start==NULL)  
       {  
           p->next=NULL;  
           p->prev=NULL;  
           start=p;  
       }  
       else  
       {  
          temp=start;  
          while(temp->next!=NULL)  
          {  
              temp=temp->next;  
          }  
          temp->next=p;  
          p->prev=temp;  
          p->next=NULL;  
          } 
       }  
    }  
void insert_locc()      //to insert the node at the specified location of the list
{  
   struct node *p,*temp;  
   int value,loc,i;  
   p=(struct node *)malloc(sizeof(struct node));  
   if(p==NULL)  
   {  
       printf("\n OVERFLOW");  
   }  
   else  
   {  
       temp=start;  
       printf("Enter the location");  
       scanf("%d",&loc);  
       for(i=0;i<loc;i++)  
       {  
           temp=temp->next;  
           if(temp==NULL)  
           {  
               printf("\n There are less than %d elements", loc);  
               return;  
           }  
       }  
       printf("Enter value: ");  
       scanf("%d",&value);  
       p->data=value;  
       p->next=temp->next;  
       p->prev=temp;  
       temp->next=p;  
       temp->next->prev=p;   
   }  
}  
void delete_begin()      //to delete the node present in the beginning of the list 
{  
    struct node *p;  
    if(start==NULL)  
    {  
        printf("\n UNDERFLOW");  
    }  
    else if(start->next==NULL)  
    {  
        start=NULL;   
        free(start);   
    }  
    else  
    {  
        p=start;  
        start=start->next;  
        start->prev=NULL;  
        free(p);   
    }  
}  
void delete_last()    //to delete the node present in the last of the list
{  
    struct node *p;  
    if(start==NULL)  
    {  
        printf("\n UNDERFLOW");  
    }  
    else if(start->next==NULL)  
    {  
        start=NULL;   
        free(start);   
    }  
    else   
    {  
        p=start;   
        if(p->next!=NULL)  
        {  
            p=p->next;   
        }  
        p->prev->next=NULL;   
        free(p);  
    }  
}  
void delete_locc()    //to delete the node present at the specified of the list 
{  
    struct node *p, *temp;  
    int val;  
    printf("\n Enter the data after which the node is to be deleted : ");  
    scanf("%d", &val);  
    p=start;  
    while(p->data!=val)  
    p=p->next;  
    if(p->next==NULL)  
    {  
        printf("\nCan't delete\n");  
    }  
    else if(p->next->next==NULL)  
    {  
        p->next=NULL;  
    }  
    else  
    {   
        temp=p->next;  
        p->next=temp->next;  
        temp->next->prev=p;  
        free(temp);   
    }     
}  
void print()  //to print the values in the list
{  
    struct node *p;  
    printf("\nvalues are:\n");  
    p=start;  
    while(p!=NULL)  
    {  
        printf("%d\n",p->data);  
        p=p->next;  
    }  
}   

OUTPUT:

Enter the operation to be performed

1.Insert in the begining
2.Insert at last
3.Insert at any specified position
4.Delete from Beginning
5.Delete from last
6.Delete node after specified location
7.Print
8.Exit
1

Enter value: 89

Enter the operation to be performed

1.Insert in the begining
2.Insert at last
3.Insert at any specified position
4.Delete from Beginning
5.Delete from last
6.Delete node after specified location
7.Print
8.Exit
1

Enter value: 65

Enter the operation to be performed

1.Insert in the begining
2.Insert at last
3.Insert at any specified position
4.Delete from Beginning
5.Delete from last
6.Delete node after specified location
7.Print
8.Exit
1

Enter value: 78

Enter the operation to be performed

1.Insert in the begining
2.Insert at last
3.Insert at any specified position
4.Delete from Beginning
5.Delete from last
6.Delete node after specified location
7.Print
8.Exit
2

Enter value: 84

Enter the operation to be performed

1.Insert in the begining
2.Insert at last
3.Insert at any specified position
4.Delete from Beginning
5.Delete from last
6.Delete node after specified location
7.Print
8.Exit
7

values are:
78
65
89
84

Enter the operation to be performed

1.Insert in the begining
2.Insert at last
3.Insert at any specified position
4.Delete from Beginning
5.Delete from last
6.Delete node after specified location
7.Print
8.Exit
5

Enter the operation to be performed

1.Insert in the begining
2.Insert at last
3.Insert at any specified position
4.Delete from Beginning
5.Delete from last
6.Delete node after specified location
7.Print
8.Exit
7

values are:
78

Enter the operation to be performed

1.Insert in the begining
2.Insert at last
3.Insert at any specified position
4.Delete from Beginning
5.Delete from last
6.Delete node after specified location
7.Print
8.Exit
8

Circular linked list

A circular linked list is a linked list in which the last node of the list points to the 'start' node of the list making a data structure look like a circle.

Types of circular linked list

-Circular singly linked list
-Circular doubly linked list

Circular singly linked list

Circular singly linked list is similar to that of singly linked list as it has a node which consists of two fields, data and link field but there is only one difference that is in circular singly linked list the last node of the list points to the first node of the list making a data structure look like a circle.

Operations on Circular singly linked list

1. Insertion:

The insertion operation in linked list is used to insert the new node. The insertion of node in singly linked list can be performed at different positions.

a) Insertion at the beginning:

  • While inserting a new node there can be two possibilities. Either the list is empty or there's at least one node in the list.
  • First we will allocate memory for the new node.
    p=(struct node)malloc(sizeof(struct ndoe));*
  • If the condition (start==NULL) is satisfied it means the list is empty. So this node will point to itself only.The 'start' pointer will also point to the inserted node.
  • If the condition (start==NULL) is false which means that the list contains at least one node. In this case, we need to traverse the list in order to reach the last node of the list.
if(start==NULL)  
{  
    start=p;  
    p->next=start;  
} 
temp=start;  
while(temp->next!=start)  
temp=temp->next;
temp->next=p;   
p->next=start;   //the next pointer of 'temp' will point to the existing 'start' node of the list 
start=p;         //make the new node 'p', the new  node of the circular singly linked list

At the end of the loop, the pointer temp would point to the last node of the list. Since, in a circular singly linked list, the last node of the list contains a pointer to the first node of the list. Therefore, we need to make the next pointer of the last node point to the 'start' node of the list and the new node which is being inserted into the list will be the new 'start' node of the list therefore the next pointer of temp will point to the new node 'p'.

b) Insertion at the end:

There can be two cases while inserting a new node at the end of the circular singly linked list. Either the list is empty or there is at least one node in the existing list.

  • Allocate memory to the new node.
  • In the first case, the condition(start==NULL) is satisfied. Since we are working on circular singly linked list then we have to make the pointer of the new node to point to itself.
struct node *p=(struct node *)malloc(sizeof(struct node));
if(start==NULL)  
{  
start=p;  
p->next=start;
}
  • In the second case, there is at least one node in the list.In this, we have to traverse the list in order to reach the last node.
  • When the last node is reached, the pointer temp would point to the last node of the list.Since, the new node which is being inserted into the list will be the new last node of the list. Therefore the existing last node i.e. 'temp' must point to the new node 'p'.
  • The new last node of the list i.e. 'p' will point to the 'start' node of the list.
temp=start;  
while(temp->next!start)  
temp=temp->next;
temp->next=p;
p->next=start;

2. Deletion:

In circular singly linked list deletion operation can be performed in many ways.

a) Deletion in the beginning

There can be three cases while deleting a node at the beginning of a circular singly linked list.

  • case 1: when the list is empty. So the condition (start=NULL) will be satisfied and underflow will be printed.
if(start==NULL)  
{  
printf("\nUNDERFLOW");    
return;   
}
  • case 2: list contains single node. Here,the condition (start->next==start) will be satisfied. In this case, we have only one node so we will delete it(start pointer) and make the 'start' pointer free.
if(start->next==start)  
{  
start=NULL;  
free(start);  
}  
  • case 3: list contains more than one node. In that case, we need to traverse the list by using the pointer 'p' to reach the last node of the list.At the end of the loop, the pointer 'p' point to the last node of the list. Since, the last node of the list points to the 'start' node of the list.
p=start;   
while(p->next!=start)  
p=p->next; 
p->next=start->next; 
free(start); 

b) Deletion at the end

There can be three cases while deleting a node at the end of a circular singly linked list.

  • case 1: when the list is empty. So the condition (start==NULL) will be satisfied and underflow will be printed.
if(start==NULL)  
{  
printf("\nUNDERFLOW");    
return;   
}
  • case 2: list contains single node. Here,the condition (start->next==start) will be satisfied. In this case, we have only one node so we will delete it(start pointer) and make the 'start' pointer free.
if(start->next==start)  
{  
start=NULL;  
free(start);  
}  
  • case 3: list contains more than one element, then in order to delete the last element, we need to reach the last node. We also need to keep track of the second last node of the list.
p=start;  
while(p->next!=start)  
{  
prep=p;  
p=p->next;  
}  
prep->next=p->next;  
free(p); 

A complete program of different types of operations on circular singly linked list

#include<stdio.h>  
#include<stdlib.h>  
struct node   
{  
    int data;  
    struct node *next;   
};  
struct node *start;    
/*fuction declaration of all the operations*/
void insert_begin();   
void insert_last();    
void delete_begin();  
void delete_last();   
void print();  
void main ()  
{  
int ch=0;  
    while(ch!=6)   
    {  
        printf("\nEnter the operation to be performed\n");
        printf("\n1.Insert in begining\n2.Insert at last\n3.Delete from Beginning\n4.Delete from last\n5.Print\n6.Exit\n");          
        scanf("\n%d",&ch);  
        switch(ch)  
        {  
             /*function calls of all the operations */
            case 1:  
            insert_begin();       
            break;  
            case 2:  
            insert_last();         
            break;    
            case 3:  
            delete_begin();       
            break;  
            case 4:  
            delete_last();        
            break;  
            case 5:
            print();        
            break;  
            case 6:  
            exit(0);  
            break;  
            default:  
            printf("Enter valid option");
        }  
    }  
}  
void insert_begin()  
{  
    struct node *p,*temp;   
    int value;   
    p=(struct node *)malloc(sizeof(struct node));  
    if(p==NULL)  
    {  
        printf("\nOVERFLOW");  
    }  
    else   
    {  
        printf("\nEnter the value: ");  
        scanf("%d",&value);  
        p->data=value;  
        if(start==NULL)  
        {  
            start=p;  
            p->next=start;  
        }  
        else   
        {     
            temp=start;  
            while(temp->next!=start)  
                temp=temp->next;  
            p->next=start;   
            temp->next=p;   
            start=p;  
        }     
	}                   
}  
void insert_last()  
{  
    struct node *p,*temp;   
    int value;  
    p=(struct node *)malloc(sizeof(struct node));  
    if(p==NULL)  
    {  
        printf("\nOVERFLOW\n");  
    }  
    else  
    {  
        printf("\nEnter value:");  
        scanf("%d",&value);  
        p->data=value;  
        if(start==NULL)  
        {  
            start=p;  
            p->next=start;    
        }  
        else  
        {  
            temp=start;  
            while(temp->next!=start)  
            {  
                temp=temp->next;  
            }  
            temp->next=p;   
            p->next=start;  
        }   
    }   
} 
void delete_begin()  
{  
    struct node *p;   
    if(start==NULL)  
    {  
        printf("\nUNDERFLOW");    
    }  
    else if(start->next==start)  
    {  
        start=NULL;  
        free(start);  
    }  
    else  
    {   p=start;   
        while(p->next!=start)  
            p=p->next;   
        p->next=start->next;  
        free(start);  
        start=p->next;   
    }  
}  
void delete_last()  
{  
    struct node *p, *prep;  
    if(start==NULL)  
    {  
        printf("\nUNDERFLOW");  
    }  
    else if (start->next==start)  
    {  
        start=NULL;  
        free(start);  //node will be deleted
    }  
    else   
    {  
        p=start;  
        while(p->next!=start)  
        {  
            prep=p;  
            p=p->next;  
        }  
        prep->next=p->next;  
        free(p);    //node deleted
    }  
}  
void print()  
{  
    struct node *p;  
    p=start;  
    if(start==NULL)  
    {  
        printf("\nnothing to print");  
    }     
    else  
    {  
        printf("\n printing values \n");  
        while(p->next!=start)  
        {  
            printf("%d\n",p->data);  
            p=p->next;  
        }  
        printf("%d\n",p->data);  
    }      
}  

OUTPUT:

Enter the operation to be performed

1.Insert in begining
2.Insert at last
3.Delete from Beginning
4.Delete from last
5.Print
6.Exit
1

Enter the value: 89

Enter the operation to be performed

1.Insert in begining
2.Insert at last
3.Delete from Beginning
4.Delete from last
5.Print
6.Exit
1

Enter the value: 65

Enter the operation to be performed

1.Insert in begining
2.Insert at last
3.Delete from Beginning
4.Delete from last
5.Print
6.Exit
1

Enter the value: 88

Enter the operation to be performed

1.Insert in begining
2.Insert at last
3.Delete from Beginning
4.Delete from last
5.Print
6.Exit
5

 printing values ...
88
65
89

Enter the operation to be performed

1.Insert in begining
2.Insert at last
3.Delete from Beginning
4.Delete from last
5.Print
6.Exit
4

Enter the operation to be performed

1.Insert in begining
2.Insert at last
3.Delete from Beginning
4.Delete from last
5.Print
6.Exit
5

 printing values 
88
65

Enter the operation to be performed

1.Insert in begining
2.Insert at last
3.Delete from Beginning
4.Delete from last
5.Print
6.Exit

Circular doubly linked list

Circular doubly linked list is the complex type of linked list. In this a particular node contains three fields i.e, data field, pointer to previous node, pointer to the next node.It does not contain NULL in any of the node.
The last node of the doubly linked list holds the address of the first node of the list and the first node holds the address of the last node of the list.

Operations on Circular doubly linked list

1. Insertion:

The insertion operation in circular doubly linked list is used to insert the new node. The insertion of node can be performed at different positions.

a) Insertion at the beginning:

  • There can be two cases while inserting the new node in the list. Either the list is empty or there is at least one element in the list.
  • First we will allocate the memory to the new node.
  • In the first case, the condition (start==NULL) will be satisfied as the new node will be the first node of the list and the previous and next pointer of the new node will point to itself.
p=(struct node *)malloc(sizeof(struct node));
start=p;  
p->next=start;   
p->prev=start;
  • In the second case, the condition (start==NULL) will not be satisfied. Here, we need to reach the last node of the list through traversing the list.
  • At the end,temp must contain the address of the new node 'p' into its next part as the node which is to be inserted will be the first node.
temp=start;   
while(temp->next!=start)  
{  
    temp=temp->next;   
}
temp->next=p;  
    p->prev=temp;  
    start->prev=p;  
    p->next=start;  
    start=p; 

b) Insertion at the end:

  • There can be two cases while inserting the new node in the list at the end. Either the list is empty or there is at least one element in the list.
  • First we will allocate the memory to the new node.
  • In the first case, the condition (start==NULL) will be satisfied as the new node will be the first node of the list and the previous and next pointer of the new node will point to itself.
p=(struct node *)malloc(sizeof(struct node));
start=p;  
p->next=start;   
p->prev=start;
  • In the second case, the condition (start==NULL) will not be satisfied. As the new node will be inserted at the end of the list. The new node will hold the address of the first node therefore we need to make the next pointer of the last node point to the 'start' node of the list and the previous pointer of the 'start' node will point to the last node.
start->prev=p;  
p->next=start;
temp->next=p;  
p->prev=temp; 

2. Deletion:

The deletion operation in circular doubly linked list is used to delete the node from the list. The deletion of node can be performed at different positions.

a) Deletion at the beginning:

There can be two cases while deleting a node at the beginning of a circular doubly linked list.

  • In the first case, the ndode which is to be deleted can be the only node of the list. So the condition (start->next==start) will be satisfied, therefore the list needs to be completely deleted.
start=NULL;   
free(start); 
  • In the second case, the list contains more than one element in the list, therefore the condition (start->next==start) will not be satisfied. Now we will use a while loop to reach to the last node of the list and modify some pointers, 'temp' will point to the last node of the list. The first node of the list i.e. pointed by 'start' pointer, will need to be deleted. Therefore the last node must contain the address of the node that is pointed by the next pointer of the 'start' node.
temp=start;   
while(temp->next!=start)   
    temp=temp->next;
temp->next=start->next; 
start->next->prev=temp;
free(start);  
start=temp->next;

b) Deletion at the end:

There can be two cases while deleting a node at he end of a circular doubly linked list.

  • First case is when the node which is to be deleted can be the only node present in the linked list. So, the condition (start->next==start) will be satisfied and the list needs to be completely deleted.
start=NULL;   
free(start); 
  • In the second case, the list contains more than one element in the list, therefore the condition (start->next==start) will not be satisfied. Now we will use a while loop to reach the last node of the list. Now, 'temp' will point to the node which is to be deleted from the list. Make the next pointer of previous node of temp, point to the 'start' node of the list.
temp=start;  
while(temp->next!=start)  
    temp=temp->next; 
temp->prev->next=start; 
start->prev=p->prev;    
free(start)

A complete program of different types of operations on circular doubly linked list

#include<stdio.h>  
#include<stdlib.h>  
struct node  
{  
    struct node *prev;  
    struct node *next;  
    int data;  
};  
struct node *start;  
void insert_begin();  
void insert_last();  
void delete_begin();  
void delete_last();  
void print();    
void main ()  
{  
int ch=0;  
    while(ch!=6)  
    {  
        printf("\nEnter the operation to be performed\n");
        printf("\n1.Insert in begining\n2.Insert at last\n3.Delete from Beginning\n4.Delete from last\n5.Print\n6.Exit\n");          
        scanf("\n%d",&ch);  
        switch(ch)
        {  
            case 1:  
            insert_begin();       
            break;  
            case 2:  
            insert_last();         
            break;    
            case 3:  
            delete_begin();       
            break;  
            case 4:  
            delete_last();        
            break;  
            case 5:
            print();        
            break;  
            case 6:  
            exit(0);  
            break;  
            default:  
            printf("Enter valid option");
        }  
    }  
}  
void insert_begin()  
{  
   struct node *p,*temp;   
   int value;  
   p=(struct node *)malloc(sizeof(struct node));  
   if(p==NULL)  
   {  
       printf("\nOVERFLOW");  
   }  
   else  
   {  
    printf("\nEnter the value:");  
    scanf("%d",&value);  
    p->data=value;  
   if(start==NULL)  
   {  
      start=p;  
      p->next=start;   
      p->prev=start;   
   }  
   else   
   {  
       temp=start;   
    while(temp->next!=start)  
    {  
        temp=temp->next;   
    }  
    temp->next=p;  
    p->prev=temp;  
    start->prev=p;  
    p->next=start;  
    start=p;  
   }   
}  
}  
void insert_last()  
{  
   struct node *p,*temp;  
   int value;  
   p=(struct node *) malloc(sizeof(struct node));  
   if(p==NULL)  
   {  
       printf("\nOVERFLOW");  
   }  
   else  
   {  
       printf("\nEnter value");  
       scanf("%d",&value);  
        p->data=value;  
       if(start==NULL)  
       {  
           start=p;  
           p->next=start;   
           p->prev=start;   
       }  
       else  
       {  
          temp=start;  
          while(temp->next!=start)  
          {  
              temp=temp->next;  
          }  
          temp->next=p;  
          p->prev=temp;  
          start->prev=p;  
      p->next=start;  
        }  
   }    
}  
  
void delete_begin()  
{  
    struct node *temp;  
    if(start==NULL)  
    {  
        printf("\n UNDERFLOW");  
    }  
    else if(start->next==start)  
    {  
        start=NULL;   
        free(start);    
    }  
    else  
    {  
        temp=start;   
        while(temp->next!=start)  
        {  
            temp=temp->next;  
        }  
        temp->next=start->next;  
        start->next->prev=temp;  
        free(start);  
        start=temp->next;  
    }  
}  
void delete_last()  
{  
    struct node *p;  
    if(start==NULL)  
    {  
        printf("\n UNDERFLOW");  
    }  
    else if(start->next==start)  
    {  
        start=NULL;   
        free(start);     
    }  
    else   
    {  
        p=start;   
        if(p->next!=start)  
        {  
            p=p->next;   
        }  
        p->prev->next=start;  
        start->prev=p->prev;    
        free(p);   
    }  
}  
  
void print()
{  
    struct node *p;  
    p=start;  
    if(start==NULL)  
    {  
        printf("\nnothing to print");  
    }     
    else  
    {  
        printf("\n printing values \n");  
        while(p->next!=start)  
        {  
            printf("%d\n", p->data);  
            p=p->next;  
        }  
        printf("%d\n", p->data);  
    }  
} 

OUTPUT:

Enter the operation to be performed

1.Insert in begining
2.Insert at last
3.Delete from Beginning
4.Delete from last
5.Print
6.Exit
1

Enter the value:89

Enter the operation to be performed

1.Insert in begining
2.Insert at last
3.Delete from Beginning
4.Delete from last
5.Print
6.Exit
1

Enter the value:65

Enter the operation to be performed

1.Insert in begining
2.Insert at last
3.Delete from Beginning
4.Delete from last
5.Print
6.Exit
1

Enter the value:77

Enter the operation to be performed

1.Insert in begining
2.Insert at last
3.Delete from Beginning
4.Delete from last
5.Print
6.Exit
5

 printing values 
77
65
89

Enter the operation to be performed

1.Insert in begining
2.Insert at last
3.Delete from Beginning
4.Delete from last
5.Print
6.Exit
3

Enter the operation to be performed

1.Insert in begining
2.Insert at last
3.Delete from Beginning
4.Delete from last
5.Print
6.Exit
5

 printing values 
65
89

Enter the operation to be performed

1.Insert in begining
2.Insert at last
3.Delete from Beginning
4.Delete from last
5.Print
6.Exit
2

Enter value24

Enter the operation to be performed

1.Insert in begining
2.Insert at last
3.Delete from Beginning
4.Delete from last
5.Print
6.Exit
5

 printing values 
65
89
24

Enter the operation to be performed

1.Insert in begining
2.Insert at last
3.Delete from Beginning
4.Delete from last
5.Print
6.Exit