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)