Launch your tech mastery with us—your coding journey starts now!
Course Content
Data Structure

Types of Linked Lists

Depending on how the nodes are connected, linked lists are classified into three types:

A. Singly Linked List

A Singly Linked List is the simplest type of linked list. In this structure, each node contains data and a reference (pointer) to the next node in the sequence. The last node points to null, indicating the end of the list.

Key Characteristics:

  • Unidirectional: You can only traverse the list in one direction (Head $\to$ Tail). You cannot go back to the previous node.
  • Memory Efficient: It requires less memory per node compared to a doubly linked list because it only stores one pointer.

Code Node Structure

As seen in your Stack implementation, the node for a singly linked list is defined with just data and next :

JavaPythonCC++

class Node {
    int data;
    Node next; // Reference to the next node

    public Node(int data) {
        this.data = data;
        this.next = null; // Ends with null by default
    }
}

class Node:

    def __init__(self, data):
        self.data = data
        self.next = None  # Reference to the next node

#include <stdio.h>
#include <stdlib.h>

struct Node {
    int data;
    struct Node* next; // Reference to the next node
};

struct Node* createNode(int data) {

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

    newNode->data = data;
    newNode->next = NULL; // Ends with NULL by default

    return newNode;
}

#include <iostream>
using namespace std;

class Node {

public:
    int data;
    Node* next; // Reference to the next node

    Node(int data) {
        this->data = data;
        this->next = NULL; // Ends with null by default
    }
};

  • Navigation: Forward only.
  • Memory: Uses less memory (only one pointer per node).
  • Analogy: A conga line where everyone holds the waist of the person in front.

B. Doubly Linked List

A Doubly Linked List is a more complex structure where each node contains three parts instead of two. It allows traversal in both directions.

Node Architecture:

  1. Prev: A pointer to the previous node.
  2. Data: The value stored.
  3. Next: A pointer to the next node.

Code Implementation

The Node class expands to include the prev pointer.

JavaPythonCC++

class DoublyNode {
    int data;
    DoublyNode next;
    DoublyNode prev; // New pointer for backward navigation

    public DoublyNode(int data) {
        this.data = data;
        this.next = null;
        this.prev = null;
    }
}

public class DoublyLinkedList {

    DoublyNode head;

    // Insert at the beginning
    public void push(int data) {

        DoublyNode newNode = new DoublyNode(data);

        newNode.next = head; // 1. New node points to current head
        newNode.prev = null; // 2. New node's prev is null (it's new head)

        if (head != null) {
            head.prev = newNode; // 3. Old head's prev points to new node
        }

        head = newNode; // 4. Update head
    }
}

class DoublyNode:

    def __init__(self, data):
        self.data = data
        self.next = None
        self.prev = None  # Pointer for backward navigation


class DoublyLinkedList:

    def __init__(self):
        self.head = None


    # Insert at the beginning
    def push(self, data):

        newNode = DoublyNode(data)

        newNode.next = self.head   # 1. New node points to current head
        newNode.prev = None        # 2. New node's prev is None

        if self.head is not None:
            self.head.prev = newNode  # 3. Old head's prev points to new node

        self.head = newNode  # 4. Update head

#include <stdio.h>
#include <stdlib.h>

struct DoublyNode {
    int data;
    struct DoublyNode* next;
    struct DoublyNode* prev; // Pointer for backward navigation
};

struct DoublyNode* head = NULL;


// Insert at the beginning
void push(int data) {

    struct DoublyNode* newNode = (struct DoublyNode*)malloc(sizeof(struct DoublyNode));

    newNode->data = data;

    newNode->next = head; // 1. New node points to current head
    newNode->prev = NULL; // 2. New node's prev is NULL

    if (head != NULL) {
        head->prev = newNode; // 3. Old head's prev points to new node
    }

    head = newNode; // 4. Update head
}

#include <iostream>
using namespace std;

class DoublyNode {

public:
    int data;
    DoublyNode* next;
    DoublyNode* prev; // Pointer for backward navigation

    DoublyNode(int data) {
        this->data = data;
        this->next = NULL;
        this->prev = NULL;
    }
};


class DoublyLinkedList {

public:
    DoublyNode* head;

    DoublyLinkedList() {
        head = NULL;
    }

    // Insert at the beginning
    void push(int data) {

        DoublyNode* newNode = new DoublyNode(data);

        newNode->next = head; // 1. New node points to current head
        newNode->prev = NULL; // 2. New node's prev is NULL

        if (head != NULL) {
            head->prev = newNode; // 3. Old head's prev points to new node
        }

        head = newNode; // 4. Update head
    }
};

Advantages vs. Disadvantages

  • Pros: Can traverse both ways. Deletion is easier because you have access to the previous node immediately.
  • Cons: Consumes more memory (extra pointer). Code is slightly more complex to maintain (must update two pointers for every insertion/deletion).

Real-Life Analogy

Web Browser History: You can click “Back” to go to the previous page (prev pointer) or “Forward” to go to the next page (next pointer). The browser maintains a link in both directions.

C. Circular Linked List

A Circular Linked List is a variation where the list has no end. The last node’s next pointer, instead of pointing to null, points back to the Head (first node). This forms a continuous loop.

Types of Circular Lists:

  1. Circular Singly Linked List: Simple nodes, but the tail connects to the head.
  2. Circular Doubly Linked List: Doubly nodes, where tail connects to head and head connects to tail.

Code Logic (Singly Circular)

Notice that we never set next to null.

JavaPythonCC++

public class CircularLinkedList {
    Node head = null;
    Node tail = null;

    public void add(int data) {
        Node newNode = new Node(data);

        if (head == null) {
            // If list is empty, point head to new node
            head = newNode;
            tail = newNode;
            newNode.next = head; // Point back to itself
        } else {
            // Standard insertion
            tail.next = newNode; // Old tail points to new node
            tail = newNode;      // Update tail
            tail.next = head;    // **CRITICAL**: New tail points back to Head
        }
    }

    // Traversal requires a do-while loop to avoid infinite loops
    public void display() {
        if (head == null) return;
        Node current = head;
        do {
            System.out.print(current.data + " -> ");
            current = current.next;
        } while (current != head); // Stop when we return to start
        System.out.println("(Head)");
    }
}

class Node:
    def __init__(self, data):
        self.data = data
        self.next = None


class CircularLinkedList:

    def __init__(self):
        self.head = None
        self.tail = None


    def add(self, data):

        newNode = Node(data)

        if self.head is None:
            # If list is empty
            self.head = newNode
            self.tail = newNode
            newNode.next = self.head  # Point back to itself

        else:
            # Standard insertion
            self.tail.next = newNode
            self.tail = newNode
            self.tail.next = self.head  # New tail points back to head


    def display(self):

        if self.head is None:
            return

        current = self.head

        while True:
            print(current.data, "->", end=" ")
            current = current.next
            if current == self.head:
                break

        print("(Head)")

#include <stdio.h>
#include <stdlib.h>

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

struct Node* head = NULL;
struct Node* tail = NULL;


void add(int data) {

    struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
    newNode->data = data;

    if (head == NULL) {
        // If list is empty
        head = newNode;
        tail = newNode;
        newNode->next = head;
    }

    else {
        tail->next = newNode;
        tail = newNode;
        tail->next = head;
    }
}


void display() {

    if (head == NULL) return;

    struct Node* current = head;

    do {
        printf("%d -> ", current->data);
        current = current->next;
    } while (current != head);

    printf("(Head)\n");
}

#include <iostream>
using namespace std;

class Node {

public:
    int data;
    Node* next;

    Node(int data) {
        this->data = data;
        this->next = NULL;
    }
};


class CircularLinkedList {

public:
    Node* head = NULL;
    Node* tail = NULL;


    void add(int data) {

        Node* newNode = new Node(data);

        if (head == NULL) {
            // If list is empty
            head = newNode;
            tail = newNode;
            newNode->next = head;
        }

        else {
            tail->next = newNode;
            tail = newNode;
            tail->next = head;
        }
    }


    void display() {

        if (head == NULL) return;

        Node* current = head;

        do {
            cout << current->data << " -> ";
            current = current->next;
        } while (current != head);

        cout << "(Head)" << endl;
    }
};

Real-Life Analogy

  • Monopoly Board Game: The board is a continuous loop. After the last space (Boardwalk), you move right back to the first space (Go).
  • Music Playlist (Repeat All): When the last song finishes, the player automatically starts the first song again.

Comparison Table for Your Course

Feature Singly Linked List Doubly Linked List Circular Linked List
Direction Forward Only Forward & Backward Forward (Loops back)
Memory Low (1 pointer) High (2 pointers) Low (1 pointer)
Insertion Fast Moderate (more pointers to update) Fast
End of List Points to null Points to null Points to Head
Best Use Simple stacks/queues Music players, Undo/Redo CPU Scheduling, Games