You are on page 1of 63

Linked List Data Structure

In this tutorial, you will learn about linked list data structure and it's implementation in Python,
Java, C, and C++.

A linked list data structure includes a series of connected nodes. Here, each node store the data
and the address of the next node. For example,

LinkedList Data Structure

You have to start somewhere, so we give the address of the first node a special name
called HEAD.
Also, the last node in the linked list can be identified because its next portion points to NULL.
You might have played the game Treasure Hunt, where each clue includes the information about
the next clue. That is how the linked list operates.

Representation of LinkedList

Let's see how each node of the LinkedList is represented. Each node consists:

 A data item

 An address of another node

We wrap both the data item and the next node reference in a struct as:

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

Understanding the structure of a linked list node is the key to having a grasp on it.
Each struct node has a data item and a pointer to another struct node. Let us create a simple
Linked List with three items to understand how this works.

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

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

/* Assign data values */


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

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

/* Save address of first node in head */


head = one;

In just a few steps, we have created a simple linked list with three nodes.

LinkedList Representation
The power of LinkedList comes from the ability to break the chain and rejoin it. E.g. if you
wanted to put an element 4 between 1 and 2, the steps would be:

 Create a new struct node and allocate memory to it.

 Add its data value as 4


 Point its next pointer to the struct node containing 2 as the data value

 Change the next pointer of "1" to the node we just created.

Doing something similar in an array would have required shifting the positions of all the
subsequent elements.

// Linked list implementation in C++

#include <bits/stdc++.h>
using namespace std;

// Creating a node
class Node {
public:
int value;
Node* next;
};

int main() {
Node* head;
Node* one = NULL;
Node* two = NULL;
Node* three = NULL;

// allocate 3 nodes in the heap


one = new Node();
two = new Node();
three = new Node();

// Assign value values


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

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

// print the linked list value


head = one;
while (head != NULL) {
printf("%d ", head->value);
head = head->next;
}
}
There are three common types of Linked List.

1. Singly Linked List


2. Doubly Linked List
3. Circular Linked List

Linked List Operations: Traverse, Insert and Delete


In this tutorial, you will learn different operations on a linked list. Also, you will find
implementation of linked list operations in C/C++, Python and Java.
Now that you have got an understanding of the basic concepts behind linked list and their types,
it's time to dive into the common operations that can be performed.
Two important points to remember:
 head points to the first node of the linked list
 next pointer of the last node is NULL, so if the next current node is NULL, we have
reached the end of the linked list.
In all of the examples, we will assume that the linked list has three nodes 1 --->2 --->3 with node
structure as below:

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

How to Traverse a Linked List

Displaying the contents of a linked list is very simple. We keep moving the temp node to the
next one and display its contents.

When temp is NULL, we know that we have reached the end of the linked list so we get out of
the while loop.

struct node *temp = head;


printf("\n\nList elements are - \n");
while(temp != NULL)
{
printf("%d --->",temp->data);
temp = temp->next;
}

The output of this program will be:

List elements are -


1 --->2 --->3 --->

How to Add Elements to a Linked List

You can add elements to either the beginning, middle or end of the linked list.

Add to the beginning

 Allocate memory for new node

 Store data

 Change next of new node to point to head

 Change head to point to recently created node

struct node *newNode;


newNode = malloc(sizeof(struct node));
newNode->data = 4;
newNode->next = head;
head = newNode;

Add to the End

 Allocate memory for new node

 Store data

 Traverse to last node

 Change next of last node to recently created node


struct node *newNode;
newNode = malloc(sizeof(struct node));
newNode->data = 4;
newNode->next = NULL;

struct node *temp = head;


while(temp->next != NULL){
temp = temp->next;
}

temp->next = newNode;

Add to the Middle

 Allocate memory and store data for new node

 Traverse to node just before the required position of new node

 Change next pointers to include new node in between

struct node *newNode;


newNode = malloc(sizeof(struct node));
newNode->data = 4;

struct node *temp = head;

for(int i=2; i < position; i++) {


if(temp->next != NULL) {
temp = temp->next;
}
}
newNode->next = temp->next;
temp->next = newNode;
How to Delete from a Linked List

You can delete either from the beginning, end or from a particular position.

Delete from beginning

 Point head to the second node

head = head->next;

Delete from end

 Traverse to second last element

 Change its next pointer to null

struct node* temp = head;


while(temp->next->next!=NULL){
temp = temp->next;
}
temp->next = NULL;

Delete from middle

 Traverse to element before the element to be deleted

 Change next pointers to exclude the node from the chain

for(int i=2; i< position; i++) {


if(temp->next!=NULL) {
temp = temp->next;
}
}

temp->next = temp->next->next;
Linked List In C++
We will take a look at the singly linked list in detail in this tutorial.

The following diagram shows the structure of a singly linked list.

As shown above, the first node of the linked list is called “head” while the last node is called “Tail”.
As we see, the last node of the linked list will have its next pointer as null since it will not have any
memory address pointed to.

Since each node has a pointer to the next node, data items in the linked list need not be stored at
contiguous locations. The nodes can be scattered in the memory. We can access the nodes anytime as
each node will have an address of the next node.

We can add data items to the linked list as well as delete items from the list easily. Thus it is possible
to grow or shrink the linked list dynamically. There is no upper limit on how many data items can be
there in the linked list. So as long as memory is available, we can have as many data items added to
the linked list.

Apart from easy insertion and deletion, the linked list also doesn’t waste memory space as we need
not specify beforehand how many items we need in the linked list. The only space taken by linked
list is for storing the pointer to the next node that adds a little overhead.

Next, we will discuss the various operations that can be performed on a linked list.

Operations
Just like the other data structures, we can perform various operations for the linked list as well. But
unlike arrays, in which we can access the element using subscript directly even if it is somewhere in
between, we cannot do the same random access with a linked list.

In order to access any node, we need to traverse the linked list from the start and only then we can
access the desired node. Hence accessing the data randomly from the linked list proves to be
expensive.

We can perform various operations on a linked list as given below:


#1) Insertion
Insertion operation of linked list adds an item to the linked list. Though it may sound simple, given
the structure of the linked list, we know that whenever a data item is added to the linked list, we need
to change the next pointers of the previous and next nodes of the new item that we have inserted.

The second thing that we have to consider is the place where the new data item is to be added.
There are three positions in the linked list where a data item can be added.
#1) At the beginning of the linked list
A linked list is shown below 2->4->6->8->10. If we want to add a new node 1, as the first node of
the list, then the head pointing to node 2 will now point to 1 and the next pointer of node 1 will have
a memory address of node 2 as shown in the below figure.

Thus the new linked list becomes 1->2->4->6->8->10.

#2) After the given Node


Here, a node is given and we have to add a new node after the given node. In the below-linked list a-
>b->c->d ->e, if we want to add a node f after node c then the linked list will look as follows:

Thus in the above diagram, we check if the given node is present. If it’s present, we create a new
node f. Then we point the next pointer of node c to point to the new node f. The next pointer of the
node f now points to node d.

#3) At the end of the Linked List


In the third case, we add a new node at the end of the linked list. Consider we have the same linked
list a->b->c->d->e and we need to add a node f to the end of the list. The linked list will look as
shown below after adding the node.
Thus we create a new node f. Then the tail pointer pointing to null is pointed to f and the next pointer
of node f is pointed to null. We have implemented all three types of insert functions in the below C+
+ program.

In C++, we can declare a linked list as a structure or as a class. Declaring linked list as a structure is a
traditional C-style declaration. A linked list as a class is used in modern C++, mostly while using
standard template library.

In the following program, we have used structure to declare and create a linked list. It will have data
and pointer to the next element as its members.

#include <iostream>

using namespace std;

 
// A linked list node

struct Node

   int data;

   struct Node *next;

};

//insert a new node in front of the list

void push(struct Node** head, int node_data)

   /* 1. create and allocate node */

   struct Node* newNode = new Node;

 
   /* 2. assign data to node */

   newNode->data = node_data;

 
   /* 3. set next of new node as head */

   newNode->next = (*head);

 
   /* 4. move the head to point to the new node */

   (*head) = newNode;

 
//insert new node after a given node

void insertAfter(struct Node* prev_node, int node_data)

  /*1. check if the given prev_node is NULL */

if (prev_node == NULL)

   cout<<"the given previous node is required,cannot be NULL"; return; }

 
   /* 2. create and allocate new node */

   struct Node* newNode =new Node;

 
   /* 3. assign data to the node */

   newNode->data = node_data;

 
   /* 4. Make next of new node as next of prev_node */

   newNode->next = prev_node->next;

 
    /* 5. move the next of prev_node as new_node */

    prev_node->next = newNode;

 
/* insert new node at the end of the linked list */

void append(struct Node** head, int node_data)

/* 1. create and allocate node */

struct Node* newNode = new Node;

 
struct Node *last = *head; /* used in step 5*/

 
/* 2. assign data to the node */

newNode->data = node_data;

 
/* 3. set next pointer of new node to null as its the last node*/

newNode->next = NULL;

 
/* 4. if list is empty, new node becomes first node */

if (*head == NULL)

*head = newNode;

return;

 
/* 5. Else traverse till the last node */

while (last->next != NULL)

last = last->next;

 
/* 6. Change the next of last node */

last->next = newNode;

return;

 
// display linked list contents

void displayList(struct Node *node)

   //traverse the list to display each node

   while (node != NULL)

   {

      cout<<node->data<<"-->";

      node = node->next;

   }

 
if(node== NULL)

cout<<"null";

/* main program for linked list*/


int main()

/* empty list */

struct Node* head = NULL;

 
// Insert 10.

append(&head, 10);

 
// Insert 20 at the beginning.

push(&head, 20);

 
// Insert 30 at the beginning.

push(&head, 30);

 
// Insert 40 at the end.

append(&head, 40); //

 
Insert 50, after 20.

insertAfter(head->next, 50);

 
cout<<"Final linked list: "<<endl;

displayList(head);

 
return 0;

Output:
Final linked list:

30–>20–>50–>10–>40–>null

Next, we implement the linked list insert operation in Java. In Java language, the linked list is
implemented as a class. The program below is similar in logic to the C++ program, the only
difference is that we use a class for the linked list.

class LinkedList
{

   Node head; // head of list

 
   //linked list node declaration

   class Node

   int data;

   Node next;

   Node(int d) {data = d; next = null; }

 
/* Insert a new node at the front of the list */

public void push(int new_data)

   //allocate and assign data to the node

   Node newNode = new Node(new_data);

 
   //new node becomes head of linked list

   newNode.next = head;

 
   //head points to new node

   head = newNode;

 
// Given a node,prev_node insert node after prev_node

public void insertAfter(Node prev_node, int new_data)

   //check if prev_node is null.

   if (prev_node == null)

   {

      System.out.println("The given node is required and cannot be null");

      return;

   }
 
//allocate node and assign data to it

Node newNode = new Node(new_data);

 
//next of new Node is next of prev_node

newNode.next = prev_node.next;

 
//prev_node->next is the new node.

prev_node.next = newNode;

    //inserts a new node at the end of the list

public void append(intnew_data)

    {

        //allocate the node and assign data

        Node newNode = new Node(new_data);

 
        //if linked list is empty, then new node will be the head

if (head == null)

        {

head = new Node(new_data);

return;

        }

 
        //set next of new node to null as this is the last node

newNode.next = null;

 
// if not the head node traverse the list and add it to the last

Node last = head;

while (last.next != null)

last = last.next;

 
//next of last becomes new node

last.next = newNode;
return;

 
//display contents of linked list

public void displayList()

   Node pnode = head;

   while (pnode != null)

   System.out.print(pnode.data+"-->");

   pnode = pnode.next;

if(pnode == null)

System.out.print("null");

 
}

 
}

 
//Main class to call linked list class functions and construct a linked list

class Main{

public static void main(String[] args)

   {

   /* create an empty list */

   LinkedList lList = new LinkedList();

 
   // Insert 40.

   lList.append(40);

 
   // Insert 20 at the beginning.

   lList.push(20);

 
   // Insert 10 at the beginning.
   lList.push(10);

 
   // Insert 50 at the end.

   lList.append(50);

 
   // Insert 30, after 20.

   lList.insertAfter(lList.head.next, 30);

 
   System.out.println("\nFinal linked list: ");

   lList. displayList ();

   }

Output:
Final linked list:

10–>20–>30–>40–>50–>null

In both the program above, C++ as well as Java, we have separate functions to add a node in front of
the list, end of the list and between the lists given in a node. In the end, we print the contents of the
list created using all the three methods.

#2) Deletion
Like insertion, deleting a node from a linked list also involves various positions from where the node
can be deleted. We can delete the first node, last node or a random kth node from the linked list.
After deletion, we need to adjust the next pointer and the other pointers in the linked list
appropriately so as to keep the linked list intact.

In the following C++ implementation, we have given two methods of deletion i.e. deleting the first
node in the list and deleting the last node in the list. We first create a list by adding nodes to the head.
Then we display the contents of the list after insertion and each deletion.

#include <iostream>

using namespace std;

 
/* Link list node */

struct Node {

   int data;

   struct Node* next;


   };

 
//delete first node in the linked list

Node* deleteFirstNode(struct Node* head)

   if (head == NULL)

   return NULL;

 
   // Move the head pointer to the next node

   Node* tempNode = head;

   head = head->next;

   delete tempNode;

 
   return head;

//delete last node from linked list

Node* removeLastNode(struct Node* head)

   if (head == NULL)

   return NULL;

 
   if (head->next == NULL) {

      delete head;

      return NULL;

   }

 
// first find second last node

Node* second_last = head;

while (second_last->next->next != NULL)

second_last = second_last->next;

 
// Delete the last node

delete (second_last->next);
 
// set next of second_last to null

second_last->next = NULL;

 
return head;

 
// create linked list by adding nodes at head

void push(struct Node** head, int new_data)

   struct Node* newNode = new Node;

   newNode->data = new_data;

   newNode->next = (*head);

   (*head) = newNode;

 
// main function

int main()

   /* Start with the empty list */

   Node* head = NULL;

 
   // create linked list

   push(&head, 2);

   push(&head, 4);

   push(&head, 6);

   push(&head, 8);

   push(&head, 10);

 
         Node* temp;

 
   cout<<"Linked list created "<<endl; for (temp = head; temp != NULL; temp = temp->next)

   cout << temp->data << "-->";


   if(temp == NULL)

   cout<<"NULL"<<endl;

 
       //delete first node

   head = deleteFirstNode(head);

   cout<<"Linked list after deleting head node"<<endl; for (temp = head; temp != NULL; temp = temp->next)

   cout << temp->data << "-->";

   if(temp == NULL)

   cout<<"NULL"<<endl;

 
      //delete last node

   head = removeLastNode(head);

   cout<<"Linked list after deleting last node"<<endl; for (temp = head; temp != NULL; temp = temp->next)

   cout << temp->data << "-->";

   if(temp == NULL)

   cout<<"NULL";

 
   return 0;

Output:
Linked list created

10–>8–>6–>4–>2–
>NULL

Linked list after deleting head node

8–>6–>4–>2–
>NULL

Linked list after deleting last node

8–>6–>4–>NULL

Next is the Java implementation for deleting nodes from the linked list. The implementation logic is
the same as used in the C++ program. The only difference is that the linked list is declared as a class.

class Main {
 
// Linked list node /

static class Node {

      int data;

      Node next;

   };

 
// delete first node of linked list

static Node deleteFirstNode(Node head)

   if (head == null)

   return null;

 
   // Move the head pointer to the next node

   Node temp = head;

   head = head.next;

 
   return head;

 
// Delete the last node in linked list

static Node deleteLastNode(Node head)

   if (head == null)

   return null;

 
   if (head.next == null) {

   return null;

 
// search for second last node

Node second_last = head;

while (second_last.next.next != null)


second_last = second_last.next;

 
// set next of second last to null

second_last.next = null;

 
return head;

 
// Add nodes to the head and create linked list

static Node push(Node head, int new_data)

   Node newNode = new Node();

   newNode.data = new_data;

   newNode.next = (head);

   (head) = newNode;

   return head;

 
//main function

public static void main(String args[])

   // Start with the empty list /

   Node head = null;

 
        //create linked list

   head = push(head, 1);

   head = push(head, 3);

   head = push(head, 5);

   head = push(head, 7);

   head = push(head, 9);

 
        Node temp;

   System.out.println("Linked list created :");


   for (temp = head; temp != null; temp = temp.next)

   System.out.print(temp.data + "-->");

   if(temp == null)

   System.out.println("null");

 
   head = deleteFirstNode(head);

   System.out.println("Linked list after deleting head node :");

   for (temp = head; temp != null; temp = temp.next)

   System.out.print(temp.data + "-->");

   if(temp == null)

   System.out.println("null");

   head = deleteLastNode(head);

   System.out.println("Linked list after deleting last node :");

   for (temp = head; temp != null; temp = temp.next)

   System.out.print(temp.data + "-->");

   if(temp == null)

   System.out.println("null");

   }

Output:
Linked list created :

9–>7–>5–>3–>1–
>null

Linked list after deleting head node :

7–>5–>3–>1–
>null

Linked list after deleting last node :

7–>5–>3–>null

Count The Number Of Nodes


The operation to count the number of nodes can be performed while traversing the linked list. We
have already seen in the implementation above that whenever we need to insert/delete a node or
display contents of the linked list, we need to traverse the linked list from start.
Keeping a counter and incrementing it as we traverse each node will give us the count of the number
of nodes present in the linked list. We will leave this program for the readers to implement.

Arrays And Linked Lists


Having seen the operations and implementation of the linked list, let us compare how arrays and
linked list fair in comparison with each other.

Arrays Linked lists

Arrays have fixed size Linked list size is dynamic

Insertion of new element is expensive Insertion/deletion is easier

Random access is allowed Random access not possible

Elements are at contiguous location Elements have non-contiguous location

No extra space is required for the next pointer Extra memory space required for next pointer

Applications
As arrays and linked lists are both used to store items and are linear data structures, both these
structures can be used in similar ways for most of the applications.

Some of the applications for linked lists are as follows:


 A linked list can be used to implement stacks and queues.
 A linked list can also be used to implement graphs whenever we have to represent graphs as
adjacency lists.
 A mathematical polynomial can be stored as a linked list.
 In the case of hashing technique, the buckets used in hashing are implemented using the
linked lists.
 Whenever a program requires dynamic allocation of memory, we can use a linked list as
linked lists work more efficiently in this case.

Implementing Linked List Operations in C++

// Linked list operations in C++

#include <stdlib.h>
#include <iostream>
using namespace std;

// Create a node
struct Node {
int item;
struct Node* next;
};

void insertAtBeginning(struct Node** ref, int data) {

// Allocate memory to a node


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

// insert the item


new_node->item = data;
new_node->next = (*ref);

// Move head to new node


(*ref) = new_node;
}

// Insert a node after a node


void insertAfter(struct Node* prev_node, int data) {
if (prev_node == NULL) {
cout << "the given previous node cannot be NULL";
return;
}

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


new_node->item = data;
new_node->next = prev_node->next;
prev_node->next = new_node;
}

void insertAtEnd(struct Node** ref, int data) {


struct Node* new_node = (struct Node*)malloc(sizeof(struct Node));
struct Node* last = *ref;

new_node->item = data;
new_node->next = NULL;

if (*ref == NULL) {
*ref = new_node;
return;
}
while (last->next != NULL)
last = last->next;

last->next = new_node;
return;
}

void deleteNode(struct Node** ref, int key) {


struct Node *temp = *ref, *prev;

if (temp != NULL && temp->item == key) {


*ref = temp->next;
free(temp);
return;
}
// Find the key to be deleted
while (temp != NULL && temp->item != key) {
prev = temp;
temp = temp->next;
}

// If the key is not present


if (temp == NULL) return;

// Remove the node


prev->next = temp->next;

free(temp);
}

// Print the linked list


void printList(struct Node* node) {
while (node != NULL) {
cout << node->item << " ";
node = node->next;
}
}

// Driver program
int main() {
struct Node* head = NULL;

insertAtEnd(&head, 1);
insertAtBeginning(&head, 2);
insertAtBeginning(&head, 3);
insertAtEnd(&head, 4);
insertAfter(head->next, 5);

cout << "Linked list: ";


printList(head);

cout << "\nAfter deleting an element: ";


deleteNode(&head, 3);
printList(head);
}

Singly Linked List

It is the most common. Each node has data and a pointer to the next node.

Singly linked list

Node is represented as:

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

A three-member singly linked list can be created as:

/* Initialize nodes */
struct node *head;
struct node *one = NULL;
struct node *two = NULL;
struct node *three = NULL;
/* Allocate memory */
one = malloc(sizeof(struct node));
two = malloc(sizeof(struct node));
three = malloc(sizeof(struct node));

/* Assign data values */


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

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

/* Save address of first node in head */


head = one;

Doubly Linked List

We add a pointer to the previous node in a doubly-linked list. Thus, we can go in either direction:
forward or backward.

Doubly linked list

A node is represented as

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

A three-member doubly linked list can be created as

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

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

/* Assign data values */


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

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

two->next = three;
two->prev = one;

three->next = NULL;
three->prev = two;

/* Save address of first node in head */


head = one;

Doubly Linked In C++


As in the singly linked list, the doubly linked list also has a head and a tail. The previous pointer of
the head is set to NULL as this is the first node. The next pointer of the tail node is set to NULL as
this is the last node.

A basic layout of the doubly linked list is shown in the below diagram.
In the above figure, we see that each node has two pointers, one pointing to the previous node and the
other pointing to the next node. Only the first node (head) has its previous node set to null and the
last node (tail) has its next pointer set to null.

As the doubly linked list contains two pointers i.e. previous and next, we can traverse it into the
directions forward and backward. This is the main advantage of doubly linked list over the singly
linked list.

Declaration
In C-style declaration, a node of the doubly linked list is represented as follows:
struct node

struct node *prev;

int data;

struct node *next;

};

Apart from the above declaration, we can also represent a node in the doubly linked list as a class in
C++. A doubly linked list is represented as a class when we use STL in C++. We can implement a
doubly linked list using a class in Java as well.

Basic Operations
Following are some of the operations that we can perform on a doubly linked list.

Insertion
Insertion operation of the doubly linked list inserts a new node in the linked list. Depending on the
position where the new node is to be inserted, we can have the following insert operations.

 Insertion at front – Inserts a new node as the first node.


 Insertion at the end – Inserts a new node at the end as the last node.
 Insertion before a node – Given a node, inserts a new node before this node.
 Insertion after a node – Given a node, inserts a new node after this node.
Deletion
Deletion operation deletes a node from a given position in the doubly linked list.

 Deletion of the first node – Deletes the first node in the list
 Deletion of the last node – Deletes the last node in the list.
 Deletion of a node given the data – Given the data, the operation matches the data with the
node data in the linked list and deletes that node.
Traversal
Traversal is a technique of visiting each node in the linked list. In a doubly linked list, we have two
types of traversals as we have two pointers with different directions in the doubly linked list.

 Forward traversal – Traversal is done using the next pointer which is in the forward
direction.
 Backward traversal – Traversal is done using the previous pointer which is the backward
direction.
Reverse
This operation reverses the nodes in the doubly linked list so that the first node becomes the last node
while the last node becomes the first node.

Search
Search operation in the doubly linked list is used to search for a particular node in the linked list. For
this purpose, we need to traverse the list until a matching data is found.

Insertion
Insert a node at the front

Insertion of a new node at the front of the list is shown above. As seen, the previous new node N is
set to null. Head points to the new node. The next pointer of N now points to N1 and previous of N1
that was earlier pointing to Null now points to N.

Insert node at the end


Inserting node at the end of the doubly linked list is achieved by pointing the next pointer of new
node N to null. The previous pointer of N is pointed to N5. The ‘Next’ pointer of N5 is pointed to N.

Insert node before/after given node

As shown in the above diagram, when we have to add a node before or after a particular node, we
change the previous and next pointers of the before and after nodes so as to appropriately point to the
new node. Also, the new node pointers are appropriately pointed to the existing nodes.

The following C++ program demonstrates all the above methods to insert nodes in the doubly
linked list.
#include <iostream>

using namespace std;

  

// A doubly linked list node

struct Node {

   int data;

   struct Node* next;

   struct Node* prev;

};

  

//inserts node at the front of the list


void insert_front(struct Node** head, int new_data)

   //allocate memory for New node

   struct Node* newNode = new Node;

  

   //assign data to new node

   newNode->data = new_data;

  

   //new node is head and previous is null, since we are adding at the front

   newNode->next = (*head);

   newNode->prev = NULL;

  

   //previous of head is new node

   if ((*head) != NULL)

   (*head)->prev = newNode;

  

   //head points to new node

   (*head) = newNode;

/* Given a node as prev_node, insert a new node after the given node */

void insert_After(struct Node* prev_node, int new_data)

   //check if prev node is null

   if (prev_node == NULL) {

   cout<<"Previous node is required , it cannot be NULL";

   return;

   //allocate memory for new node

   struct Node* newNode = new Node;

  

   //assign data to new node

   newNode->data = new_data;

  
   //set next of newnode to next of prev node

   newNode->next = prev_node->next;

  

   //set next of prev node to newnode

   prev_node->next = newNode;

  

   //now set prev of newnode to prev node

   newNode->prev = prev_node;

  

   //set prev of new node's next to newnode

   if (newNode->next != NULL)

   newNode->next->prev = newNode;

  

//insert a new node at the end of the list

void insert_end(struct Node** head, int new_data)

   //allocate memory for node

   struct Node* newNode = new Node;

  

   struct Node* last = *head; //set last node value to head

  

   //set data for new node

   newNode->data = new_data;

  

   //new node is the last node , so set next of new node to null

   newNode->next = NULL;

  

   //check if list is empty, if yes make new node the head of list

   if (*head == NULL) {

   newNode->prev = NULL;

   *head = newNode;
    return;

  

//otherwise traverse the list to go to last node

while (last->next != NULL)

last = last->next;

  

//set next of last to new node

last->next = newNode;

  

//set last to prev of new node

newNode->prev = last;

return;

  

// This function prints contents of linked list starting from the given node

void displayList(struct Node* node) {

   struct Node* last;

  

   while (node != NULL) {

      cout<<node->data<<"<==>";

      last = node;

      node = node->next;

   }

   if(node == NULL)

   cout<<"NULL";

   }

  

//main program

int main() {

   /* Start with the empty list */

   struct Node* head = NULL;

  
   // Insert 40 as last node

   insert_end(&head, 40);

  

   // insert 20 at the head

   insert_front(&head, 20);

  

   // Insert 10 at the beginning.

   insert_front(&head, 10);

  

   // Insert 50 at the end.

   insert_end(&head, 50);

  

   // Insert 30, after 20.

   insert_After(head->next, 30);

  

   cout<<"Doubly linked list is as follows: "<<endl;

   displayList(head);

   return 0;

Output:
Doubly linked list is as follows:

10<==>20<==>30<==>40<==>50<==>NULL

The above program constructs a doubly linked list by inserting the nodes using three insertion
methods i.e. inserting the node at the front, inserting the node at the end and inserting the node after
the given node.

Next, we demonstrate the same operation as a Java implementation.


// Java Class for Doubly Linked List

class Doubly_linkedList {

   Node head; // list head

  

    /* Doubly Linked list Node*/

   class Node {

      int data;
      Node prev;

      Node next;

  

      //create a new node using constructor

      Node(int d) { data = d; }

   }

  

// insert a node at the front of the list

public void insert_front(int new_data)

   /* 1. allocate node

   * 2. put in the data */

   Node new_Node = new Node(new_data);

  

   /* 3. Make next of new node as head and previous as NULL */

   new_Node.next = head;

   new_Node.prev = null;

  

   /* 4. change prev of head node to new node */

   if (head != null)

   head.prev = new_Node;

  

   /* 5. move the head to point to the new node */

   head = new_Node;

//insert a node after the given prev node

public void Insert_After(Node prev_Node, int new_data)

   //check that prev node is not null

   if (prev_Node == null) {

   System.out.println("The previous node is required,it cannot be NULL ");

   return;

}
  

   //allocate new node and set it to data

   Node newNode = new Node(new_data);

  

   //set next of newNode as next of prev node

   newNode.next = prev_Node.next;

  

   //set new node to next of prev node

   prev_Node.next = newNode;

  

   //set prev of newNode as prev node

   newNode.prev = prev_Node;

  

   //set prev of new node's next to newnode

   if (newNode.next != null)

   newNode.next.prev = newNode;

  

// Add a node at the end of the list

void insert_end(int new_data)   {

   //allocate the node and set the data

   Node newNode = new Node(new_data);

   Node last = head; //set last as the head

   //set next of new node to null since its the last node

   newNode.next = null;

  

   //set new node as head if the list is null

   if (head == null) {

      newNode.prev = null;

      head = newNode;

      return;

   }

   //if list is not null then traverse it till the last node and set last next to last
   while (last.next != null)

   last = last.next;

  

   last.next = newNode;           //set last next to new node

  

   newNode.prev = last;           //set last as prev of new node

// display the contents of linked list starting from the given node

public void displaylist(Node node)

   Node last = null;

   while (node != null) {

      System.out.print(node.data + "<==>");

      last = node;

      node = node.next;

   }

   if(node == null)

   System.out.print("null");

   System.out.println();

  

   }

class Main{

   public static void main(String[] args)

      {

      /* Start with the empty list */

      Doubly_linkedList dll = new Doubly_linkedList();

  

      // Insert 40.

      dll.insert_end(40);

  

      // Insert 20 at the beginning.

      dll.insert_front(20);
  

      // Insert 10 at the beginning.

      dll.insert_front(10);

  

      // Insert 50 at the end.

      dll.insert_end(50);

  

      // Insert 30, after 20.

      dll.Insert_After(dll.head.next, 30);

  

      System.out.println("Doubly linked list created is as follows: ");

      dll.displaylist(dll.head);

      }

Output:
Doubly linked list created is as follows:

10<==>20<==>30<==>40<==>50<==>null

Deletion
A node can be deleted from a doubly linked list from any position like from the front, end or any
other given position or given data.

When deleting a node from the doubly linked list, we first reposition the pointer pointing to that
particular node so that the previous and after nodes do not have any connection to the node to be
deleted. We can then easily delete the node.

Consider the following doubly linked list with three nodes A, B, C. Let us consider that we need to
delete the node B.
As shown in the above series of the diagram, we have demonstrated the deletion of node B from the
given linked list. The sequence of operation remains the same even if the node is first or last. The
only care that should be taken is that if in case the first node is deleted, the second node’s previous
pointer will be set to null.

Similarly, when the last node is deleted, the next pointer of the previous node will be set to null. If in
between nodes are deleted, then the sequence will be as above.

We leave the program to delete a node from a doubly linked list. Note that the implementation will
be on the lines of the insertion implementation.

Reverse Doubly Linked List


Reversing a doubly linked list is an important operation. In this, we simply swap the previous and
next pointers of all the nodes and also swap the head and tail pointers.

Given below is a doubly linked list:


Following C++ implementation shows the Reverse Doubly Linked List.
#include <iostream>

using namespace std;

//node declaration for doubly linked list

struct Node {

   int data;

   struct Node *prev, *next;

};

  

Node* newNode(int val)

   Node* temp = new Node;

   temp->data = val;

   temp->prev = temp->next = nullptr;

   return temp;

void displayList(Node* head)

   while (head->next != nullptr) {

      cout << head->data << " <==> ";

      head = head->next;

      }
   cout << head->data << endl;

  

// Insert a new node at the head of the list

void insert(Node** head, int node_data)

   Node* temp = newNode(node_data);

   temp->next = *head;

   (*head)->prev = temp;

   (*head) = temp;

  

// reverse the doubly linked list

void reverseList(Node** head)

   Node* left = *head, * right = *head;

  

   // traverse entire list and set right next to right

   while (right->next != nullptr)

   right = right->next;

  

   //swap left and right data by moving them towards each other till they meet or cross

   while (left != right && left->prev != right) {

  

      // Swap left and right pointer data

      swap(left->data, right->data);

  

      // Advance left pointer

      left = left->next;

  

      // Advance right pointer

      right = right->prev;

   }
}

int main()

   Node* headNode = newNode(5);

   insert(&headNode, 4);

   insert(&headNode, 3);

   insert(&headNode, 2);

   insert(&headNode, 1);

   cout << "Original doubly linked list: " << endl;

   displayList(headNode);

   cout << "Reverse doubly linked list: " << endl;

   reverseList(&headNode);

   displayList(headNode);

  

   return 0;

Output:
Original doubly linked list:

1 <==> 2 <==> 3 <==> 4 <==> 5

Reverse doubly linked list:

5 <==> 4 <==> 3 <==> 2 <==> 1

Here we swap the left and right pointers and move them towards each other till they meet or cross
each other. Then the first and last nodes are swapped.

The next program is the Java implementation for reversing a doubly linked list. In this program also
we make use of swapping of the left and right nodes as we did in our previous program.

// Java Program to Reverse a doubly linked List using Data Swapping

class Main{

static class Node {

   int data;

   Node prev, next;

};
  

static Node newNode(int new_data)  {

   Node temp = new Node();

   temp.data = new_data;

   temp.prev = temp.next = null;

   return temp;

  

static void displayList(Node head)  {

   while (head.next != null)  {

   System.out.print(head.data+ " <==> ");

   head = head.next;

System.out.println( head.data );

  

// Insert a new node at the head of the list

static Node insert(Node head, int new_data)  {

   Node temp = newNode(new_data);

   temp.next = head;

   (head).prev = temp;

   (head) = temp;

   return head;

  

// Function to reverse the list

static Node reverseList(Node head)  {

    Node left = head, right = head;

   // traverse the list, set right pointer to end of list

   while (right.next != null)

   right = right.next;

   // move left and right pointers and swap their data till they meet or cross each other

   while (left != right && left.prev != right)   {


   // Swap data of left and right pointer

   int t = left.data;

   left.data = right.data;

   right.data = t;

  

   left = left.next;                        // Advance left pointer

   right = right.prev;                    // Advance right pointer

   }

return head;

public static void main(String args[])

   {

   Node headNode = newNode(5);

   headNode = insert(headNode, 4);

   headNode = insert(headNode, 3);

   headNode = insert(headNode, 2);

   headNode = insert(headNode, 1);

  

   System.out.println("Original doubly linked list:");

   displayList(headNode);

   System.out.println("Reversed doubly linked list:");

   headNode=reverseList(headNode);

   displayList(headNode);

  

   }

Output:
Original doubly linked list:

1 <==> 2 <==> 3 <==> 4 <==> 5

Reversed doubly linked list:

5 <==> 4 <==> 3 <==> 2 <==> 1
Advantages/Disadvantages Over Singly Linked List
Let us discuss some of the advantages and disadvantages of doubly linked list over the singly linked
list.

Advantages:
 The doubly linked list can be traversed in forward as well as backward directions, unlike
singly linked list which can be traversed in the forward direction only.
 Delete operation in a doubly-linked list is more efficient when compared to singly list when a
given node is given. In a singly linked list, as we need a previous node to delete the given
node, sometimes we need to traverse the list to find the previous node. This hits the
performance.
 Insertion operation can be done easily in a doubly linked list when compared to the singly
linked list.
Disadvantages:
 As the doubly linked list contains one more extra pointer i.e. previous, the memory space
taken up by the doubly linked list is larger when compared to the singly linked list.
 Since two pointers are present i.e. previous and next, all the operations performed on the
doubly linked list have to take care of these pointers and maintain them thereby resulting in a
performance bottleneck.
Applications Of Doubly Linked List
A doubly linked list can be applied in various real-life scenarios and applications as discussed below.

 A Deck of cards in a game is a classic example of a doubly linked list. Given that each card
in a deck has the previous card and next card arranged sequentially, this deck of cards can be
easily represented using a doubly linked list.
 Browser history/cache – The browser cache has a collection of URLs and can be navigated
using the forward and back buttons is another good example that can be represented as a
doubly linked list.
 Most recently used (MRU) also can be represented as a doubly linked list.
 Other data structures like Stacks, hash table, the binary tree can also be constructed or
programmed using a doubly linked list.

Circular Linked List

A circular linked list is a variation of a linked list in which the last element is linked to the first
element. This forms a circular loop.
Circul
ar linked list

A circular linked list can be either singly linked or doubly linked.

 for singly linked list, next pointer of last item points to the first item

 In the doubly linked list, prev pointer of the first item points to the last item as well.
A three-member circular singly linked list can be created as:

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

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

/* Assign data values */


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

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

/* Save address of first node in head */


head = one;
Circular Linked List In C++
The arrangement shown below is for a singly linked list.

A circular linked list can be a singly linked list or a doubly linked list. In a doubly circular linked list,
the previous pointer of the first node is connected to the last node while the next pointer of the last
node is connected to the first node.

Its representation is shown below.

Declaration
We can declare a node in a circular linked list as any other node as shown below:
struct Node
{
   int data;
   struct Node *next;
};
In order to implement the circular linked list, we maintain an external pointer “last” that points to the
last node in the circular linked list. Hence last->next will point to the first node in the linked list.

By doing this we ensure that when we insert a new node at the beginning or at the end of the list, we
need not traverse the entire list. This is because the last points to the last node while last->next points
to the first node.

This wouldn’t have been possible if we had pointed the external pointer to the first node.

Basic Operations
The circular linked list supports insertion, deletion, and traversal of the list. We will discuss each of
the operations in detail now.

Insertion
We can insert a node in a circular linked list either as a first node (empty list), in the beginning, in the
end, or in between the other nodes. Let us see each of these insertion operations using a pictorial
representation below.

#1) Insert in an empty list


When there are no nodes in circular list and the list is empty, the last pointer is null, then we insert a
new node N by pointing the last pointer to the node N as shown above. The next pointer of N will
point to the node N itself as there is only one node. Thus N becomes the first as well as last node in
the list.

#2) Insert at the beginning of the list

As shown in the above representation, when we add a node at the beginning of the list, the next
pointer of the last node points to the new node N thereby making it a first node.

N->next = last->next
Last->next = N
#3) Insert at the end of the list
To insert a new node at the end of the list, we follow these steps:
N-> next = last ->next;
last ->next = N
last = N
#4) Insert in between the list

Suppose we need to insert a new node N between N3 and N4, we first need to traverse the list and
locate the node after which the new node is to be inserted, in this case, its N3.

After the node is located, we perform the following steps.


N -> next = N3 -> next;
N3 -> next = N
This inserts a new node N after N3.

Deletion
The deletion operation of the circular linked list involves locating the node that is to be deleted and
then freeing its memory.
For this we maintain two additional pointers curr and prev and then traverse the list to locate the
node. The given node to be deleted can be the first node, the last node or the node in between.
Depending on the location we set the curr and prev pointers and then delete the curr node.

A pictorial representation of the deletion operation is shown below.

Traversal
Traversal is a technique of visiting each and every node. In linear linked lists like singly linked list
and doubly linked lists, traversal is easy as we visit each node and stop when NULL is encountered.

However, this is not possible in a circular linked list. In a circular linked list, we start from the next
of the last node which is the first node and traverse each node. We stop when we once again reach
the first node.

Now we present an implementation of the circular linked list operations using C++ and Java. We
have implemented insertion, deletion and traversal operations here. For a clear understanding, we
have depicted the circular linked list as

Thus to the last node 50, we again attach node 10 which is the first node, thereby indicating it as a
circular linked list.

#include<iostream>

using namespace std;

  

struct Node

   int data;

   struct Node *next;

};

//insert a new node in an empty list


struct Node *insertInEmpty(struct Node *last, int new_data)

   // if last is not null then list is not empty, so return

   if (last != NULL)

   return last;

  

   // allocate memory for node

   struct Node *temp = new Node;

  

   // Assign the data.

   temp -> data = new_data;

   last = temp;

  

   // Create the link.

   last->next = last;

  

   return last;

//insert new node at the beginning of the list

struct Node *insertAtBegin(struct Node *last, int new_data)

   //if list is empty then add the node by calling insertInEmpty

   if (last == NULL)

   return insertInEmpty(last, new_data);

  

   //else create a new node

   struct Node *temp = new Node;

  

   //set new data to node

   temp -> data = new_data;

   temp -> next = last -> next;

   last -> next = temp;

  
   return last;

//insert new node at the end of the list

struct Node *insertAtEnd(struct Node *last, int new_data)

   //if list is empty then add the node by calling insertInEmpty

   if (last == NULL)

   return insertInEmpty(last, new_data);

  

   //else create a new node

   struct Node *temp = new Node;

  

   //assign data to new node

   temp -> data = new_data;

   temp -> next = last -> next;

   last -> next = temp;

   last = temp;

  

   return last;

  

//insert a new node in between the nodes

struct Node *insertAfter(struct Node *last, int new_data, int after_item)

   //return null if list is empty

   if (last == NULL)

   return NULL;

  

   struct Node *temp, *p;

   p = last -> next;

   do

   {

      if (p ->data == after_item)


      {

         temp = new Node;

         temp -> data = new_data;

         temp -> next = p -> next;

         p -> next = temp;

        

         if (p == last)

         last = temp;

         return last;

       }

   p = p -> next;

 } while(p != last -> next);

  

   cout << "The node with data "<<after_item << " is not present in the list." << endl;

   return last;

  

//traverse the circular linked list

void traverseList(struct Node *last) {

   struct Node *p;

  

   // If list is empty, return.

   if (last == NULL) {

      cout << "Circular linked List is empty." << endl;

      return;

      }

p = last -> next; // Point to the first Node in the list.

  

// Traverse the list starting from first node until first node is visited again

  

do {

      cout << p -> data << "==>";

      p = p -> next;


      } while(p != last->next);

   if(p == last->next)

   cout<<p->data;

   cout<<"\n\n";

   }

  

//delete the node from the list

void deleteNode(Node** head, int key)

   // If linked list is empty retun

   if (*head == NULL)

   return;

  

   // If the list contains only a single node,delete that node; list is empty

   if((*head)->data==key && (*head)->next==*head) {

      free(*head);

      *head=NULL;

      }

Node *last=*head,*d;

  

// If key is the head

if((*head)->data==key) {

   while(last->next!=*head) // Find the last node of the list

   last=last->next;

  

   // point last node to next of head or second node of the list

   last->next=(*head)->next;

   free(*head);

   *head=last->next;

   }

  

// end of list is reached or node to be deleted not there in the list

while(last->next!=*head&&last->next->data!=key) {
   last=last->next;

// node to be deleted is found, so free the memory and display the list

if(last->next->data==key) {

      d=last->next;

      last->next=d->next;

      cout<<"The node with data "<<key<<" deleted from the list"<<endl;

      free(d);

      cout<<endl;

      cout<<"Circular linked list after deleting "<<key<<" is as follows:"<<endl;

      traverseList(last);

      }

   else

   cout<<"The node with data "<< key << " not found in the list"<<endl;

   }

  

// main Program

int main()

   struct Node *last = NULL;

  

   last = insertInEmpty(last, 30);

   last = insertAtBegin(last, 20);

   last = insertAtBegin(last, 10);

   last = insertAtEnd(last, 40);

   last = insertAtEnd(last, 60);

   last = insertAfter(last, 50,40 );

   cout<<"The circular linked list created is as follows:"<<endl;

   traverseList(last);

   deleteNode(&last,10);

   return 0;

Output:
The circular linked list created is as follows:
10==>20==>30==>40==>50==>60==>10

The node with data 10 is deleted from the list

Circular linked list after deleting 10 is as follows:

20==>30==>40==>50==>60==>20

Next, we present a Java implementation for the Circular linked list operations.
//Java class to demonstrate circular linked list operations

class Main

   static class Node {

      int data;

      Node next;

   };

//insert a new node in the empty list

static Node insertInEmpty(Node last, int new_data)

   // if list is not empty, return

   if (last != null)

   return last;

  

   Node temp = new Node(); // create a new node

  

   temp.data = new_data; // assign data to new node

   last = temp;

  

   last.next = last; // Create the link

  

   return last;

   }

//insert a new node at the beginning of the list

static Node insertAtBegin(Node last, int new_data)

   {
      //if list is null, then return and call funciton to insert node in empty list

      if (last == null)

      return insertInEmpty(last, new_data);

  

      //create a new node

      Node temp = new Node();

      //set data for the node

      temp.data = new_data;

      temp.next = last.next;

      last.next = temp;

  

      return last;

   }

//insert a new node at the end of the list

static Node insertAtEnd(Node last, int new_data)

   //if list is null, then return and call funciton to insert node in empty list

   if (last == null)

   return insertInEmpty(last, new_data);

   //create a new node

   Node temp = new Node();

  

   temp.data = new_data;

   temp.next = last.next;

   last.next = temp;

   last = temp;

  

   return last;

   }

//insert node in between the nodes in the list

static Node addAfter(Node last, int new_data, int after_item)

   {

      //if list is null, return


      if (last == null)

      return null;

  

      Node temp, p;

     p = last.next;

     do

     {

       if (p.data == after_item)

      {

         temp = new Node();

         temp.data = new_data;

         temp.next = p.next;

         p.next = temp;

     

         if (p == last)

         last = temp;

         return last;

         }

p = p.next;

   { while(p != last.next);

    

   System.out.println("The node with data " + after_item + " not present in the list.");

   return last;

  

   }

//traverse the circular linked list

static void traverse(Node last)

   Node p;

  

   // If list is empty, return.

   if (last == null) {

       System.out.println("Cicular linked List is empty.");


       return;

      }

  

p = last.next; // Point to first Node of the list.

  

// Traversing the list.

do{

      System.out.print(p.data + "==>");

      p = p.next;

      }

   while(p != last.next);

   if(p == last.next)

   System.out.print(p.data);

   System.out.print("\n\n");

   }

//delete a node from the list

static Node deleteNode(Node head, int key) {

   //if list is null, return

   if (head == null)

   return null;

  

   // Find the required node that is to be deleted

   Node curr = head, prev = new Node();

   while (curr.data != key) {

      if (curr.next == head) {

         System.out.printf("\nGiven node " + key + " is not found" + “in the list!");

           break;

         }

      prev = curr;

      curr = curr.next;

      }

// Check if node is only node

if (curr.next == head) {
   head = null;

   return head;

   }

// If more than one node, check if it is first node

if (curr == head) {

   prev = head;

   while (prev.next != head)

   prev = prev.next;

   head = curr.next;

   prev.next = head;

   }

  

// check if node is last node

else if (curr.next == head) {

   prev.next = head;

   }

else {

    prev.next = curr.next;

    }

  

System.out.println("After deleting " + key + " the circular list is:");

traverse(head);

return head;

    }

// Main code

public static void main(String[] args){

   Node last = null;

  

   last = insertInEmpty(last, 30);

   last = insertAtBegin(last, 20);

   last = insertAtBegin(last, 10);

   last = insertAtEnd(last, 40);

   last = insertAtEnd(last, 60);


   last = addAfter(last, 50, 40);

  

   System.out.println("Circular linked list created is:");

   traverse(last);

   last = deleteNode(last,40);

   }

Output:
Circular linked list created is:

10==>20==>30==>40==>50==>60==>10

After deleting 40 the circular list is:

10==>20==>30==>50==>60==>10

Advantages/Disadvantages
Let us discuss some advantages and disadvantages of the circular linked list.

Advantages:
 We can go to any node and traverse from any node. We just need to stop when we visit the
same node again.
 As the last node points to the first node, going to the first node from the last node just takes a
single step.
Disadvantages:
 Reversing a circular linked list is cumbersome.
 As the nodes are connected to form a circle, there is no proper marking for beginning or end
for the list. Hence, it is difficult to find the end of the list or loop control. If not taken care, an
implementation might end up in an infinite loop.
 We cannot go back to the previous node in a single step. We have to traverse the entire list
from first.
Applications Of Circular Linked List
 Real-time application of circular linked list can be a multi-programming operating system
wherein it schedules multiple programs. Each program is given a dedicated timestamp to
execute after which the resources are passed to another program. This goes on continuously
in a cycle. This representation can be efficiently achieved using a circular linked list.
 Games that are played with multiple players can also be represented using a circular linked
list in which each player is a node that is given a chance to play.
 We can use a circular linked list to represent a circular queue. By doing this, we can remove
the two pointers front and rear that is used for the queue. Instead, we can use only one
pointer.

You might also like