DEV Community

nk sk
nk sk

Posted on

Mastering Linked Lists in Java: Doubly and Circular Linked Lists

Linked Lists are fundamental data structures that every programmer should master. Unlike arrays, linked lists don’t require contiguous memory allocation, making them efficient for insertions and deletions.

In this blog, we’ll cover two important types of linked lists:

  • Doubly Linked List (DLL)
  • Circular Linked List (CLL)

We’ll also implement both in Java, step by step.


🔹 Doubly Linked List in Java

A Doubly Linked List has nodes that contain:

  1. Data
  2. A pointer to the previous node
  3. A pointer to the next node

This allows traversal in both forward and backward directions.

Implementation

// Node class for Doubly Linked List
class Node {
    int data;
    Node prev, next;

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

// Doubly Linked List class
class DoublyLinkedList {
    private Node head;

    // Insert at front
    public void insertFront(int data) {
        Node newNode = new Node(data);
        if (head != null) {
            newNode.next = head;
            head.prev = newNode;
        }
        head = newNode;
    }

    // Insert at end
    public void insertEnd(int data) {
        Node newNode = new Node(data);
        if (head == null) {
            head = newNode;
            return;
        }
        Node temp = head;
        while (temp.next != null) {
            temp = temp.next;
        }
        temp.next = newNode;
        newNode.prev = temp;
    }

    // Delete a node by value
    public void delete(int key) {
        Node temp = head;
        while (temp != null) {
            if (temp.data == key) {
                if (temp.prev != null) {
                    temp.prev.next = temp.next;
                } else {
                    head = temp.next; // deleting head
                }
                if (temp.next != null) {
                    temp.next.prev = temp.prev;
                }
                return;
            }
            temp = temp.next;
        }
        System.out.println("Value " + key + " not found!");
    }

    // Display forward
    public void displayForward() {
        Node temp = head;
        while (temp != null) {
            System.out.print(temp.data + " <-> ");
            temp = temp.next;
        }
        System.out.println("null");
    }

    // Display backward
    public void displayBackward() {
        Node temp = head;
        if (temp == null) return;

        // Go to the last node
        while (temp.next != null) {
            temp = temp.next;
        }

        // Print backward
        while (temp != null) {
            System.out.print(temp.data + " <-> ");
            temp = temp.prev;
        }
        System.out.println("null");
    }
}

// Demo
public class Main {
    public static void main(String[] args) {
        DoublyLinkedList dll = new DoublyLinkedList();

        dll.insertEnd(10);
        dll.insertEnd(20);
        dll.insertFront(5);
        dll.insertEnd(30);

        System.out.println("Forward Traversal:");
        dll.displayForward();

        System.out.println("Backward Traversal:");
        dll.displayBackward();

        dll.delete(20);
        System.out.println("After deleting 20:");
        dll.displayForward();
    }
}
Enter fullscreen mode Exit fullscreen mode

🔹 Circular Linked List in Java

A Circular Linked List is a variation where the last node points back to the head. This forms a circle and allows continuous traversal.

We’ll implement a Singly Circular Linked List here.

Implementation

// Node class for Circular Linked List
class CNode {
    int data;
    CNode next;

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

// Circular Linked List class
class CircularLinkedList {
    private CNode head = null;
    private CNode tail = null;

    // Insert at end
    public void insert(int data) {
        CNode newNode = new CNode(data);
        if (head == null) {
            head = newNode;
            tail = newNode;
            newNode.next = head; // point to itself
        } else {
            tail.next = newNode;
            tail = newNode;
            tail.next = head; // last node points back to head
        }
    }

    // Delete a node
    public void delete(int key) {
        if (head == null) return;

        CNode current = head, prev = null;

        // Case: deleting head
        if (head.data == key) {
            if (head == tail) {
                head = tail = null;
                return;
            }
            head = head.next;
            tail.next = head;
            return;
        }

        // Search for key
        do {
            prev = current;
            current = current.next;
            if (current.data == key) {
                prev.next = current.next;
                if (current == tail) {
                    tail = prev;
                }
                return;
            }
        } while (current != head);

        System.out.println("Value " + key + " not found!");
    }

    // Display nodes
    public void display() {
        if (head == null) {
            System.out.println("List is empty!");
            return;
        }
        CNode temp = head;
        do {
            System.out.print(temp.data + " -> ");
            temp = temp.next;
        } while (temp != head);
        System.out.println("(back to head)");
    }
}

// Demo
public class CircularMain {
    public static void main(String[] args) {
        CircularLinkedList cll = new CircularLinkedList();

        cll.insert(10);
        cll.insert(20);
        cll.insert(30);
        cll.insert(40);

        System.out.println("Circular Linked List:");
        cll.display();

        cll.delete(20);
        System.out.println("After deleting 20:");
        cll.display();
    }
}
Enter fullscreen mode Exit fullscreen mode

🔹 Key Differences

Feature Doubly Linked List (DLL) Circular Linked List (CLL)
Traversal Forward & Backward Forward (loops endlessly)
Last Node Points To null Head node
Memory Usage More (extra prev link) Less (single link)
Use Cases Deques, Navigation Round-robin tasks, Buffers

🔹 Final Thoughts

  • Doubly Linked List is useful when you need bidirectional traversal.
  • Circular Linked List is best for applications like round-robin scheduling, continuous looping structures, and buffering.

Both are powerful data structures and are widely used in real-world scenarios like operating systems, browsers (back/forward navigation), and memory management.


Top comments (0)