Circular linked lists in Javascript

A Circular Linked List is a variation of the standard linked list where the first element points to the last element and the last element points back to the first element, forming a circle. Both singly and doubly linked lists can be implemented as circular structures.

Data: 10 Data: 20 Data: 30 Head

Node Structure

First, we define a Node class that contains data and a reference to the next node:

class Node {
    constructor(data) {
        this.data = data;
        this.next = null;
    }
}

// Example of creating nodes
let node1 = new Node(10);
let node2 = new Node(20);
let node3 = new Node(30);

console.log("Node created:", node1.data);
Node created: 10

Circular Linked List Implementation

Here's a complete implementation of a circular linked list with essential operations:

class CircularLinkedList {
    constructor() {
        this.head = null;
        this.size = 0;
    }

    // Insert at the beginning
    insertAtBeginning(data) {
        const newNode = new Node(data);
        
        if (!this.head) {
            this.head = newNode;
            newNode.next = this.head; // Point to itself
        } else {
            // Find the last node
            let current = this.head;
            while (current.next !== this.head) {
                current = current.next;
            }
            
            newNode.next = this.head;
            current.next = newNode;
            this.head = newNode;
        }
        this.size++;
    }

    // Insert at the end
    insertAtEnd(data) {
        const newNode = new Node(data);
        
        if (!this.head) {
            this.head = newNode;
            newNode.next = this.head;
        } else {
            let current = this.head;
            while (current.next !== this.head) {
                current = current.next;
            }
            
            current.next = newNode;
            newNode.next = this.head;
        }
        this.size++;
    }

    // Display all nodes
    display() {
        if (!this.head) {
            console.log("List is empty");
            return;
        }
        
        let current = this.head;
        let result = [];
        
        do {
            result.push(current.data);
            current = current.next;
        } while (current !== this.head);
        
        console.log("Circular List:", result.join(" -> ") + " -> (back to " + this.head.data + ")");
    }
}

// Example usage
let cll = new CircularLinkedList();
cll.insertAtEnd(10);
cll.insertAtEnd(20);
cll.insertAtBeginning(5);
cll.display();
Circular List: 5 -> 10 -> 20 -> (back to 5)

Delete Operation

Deleting nodes in a circular linked list requires special handling:

class CircularLinkedList {
    constructor() {
        this.head = null;
        this.size = 0;
    }

    insertAtEnd(data) {
        const newNode = new Node(data);
        
        if (!this.head) {
            this.head = newNode;
            newNode.next = this.head;
        } else {
            let current = this.head;
            while (current.next !== this.head) {
                current = current.next;
            }
            current.next = newNode;
            newNode.next = this.head;
        }
        this.size++;
    }

    delete(data) {
        if (!this.head) {
            console.log("List is empty");
            return;
        }

        // If deleting head node
        if (this.head.data === data) {
            if (this.head.next === this.head) {
                // Only one node
                this.head = null;
            } else {
                // Find last node
                let current = this.head;
                while (current.next !== this.head) {
                    current = current.next;
                }
                current.next = this.head.next;
                this.head = this.head.next;
            }
            this.size--;
            return;
        }

        // Delete non-head node
        let current = this.head;
        while (current.next !== this.head && current.next.data !== data) {
            current = current.next;
        }

        if (current.next.data === data) {
            current.next = current.next.next;
            this.size--;
        } else {
            console.log("Node not found");
        }
    }

    display() {
        if (!this.head) {
            console.log("List is empty");
            return;
        }
        
        let current = this.head;
        let result = [];
        
        do {
            result.push(current.data);
            current = current.next;
        } while (current !== this.head);
        
        console.log("List:", result.join(" -> "));
    }
}

// Example usage
let list = new CircularLinkedList();
list.insertAtEnd(10);
list.insertAtEnd(20);
list.insertAtEnd(30);
list.display();

list.delete(20);
list.display();
List: 10 -> 20 -> 30
List: 10 -> 30

Key Advantages and Use Cases

Advantage Use Case
Continuous traversal Round-robin scheduling
No null pointers Music playlist loops
Efficient insertion at beginning Buffer implementations
Memory efficiency Game turn management

Key Points

  • The last node's next pointer points back to the first node
  • No node has a null next pointer (unlike linear linked lists)
  • Traversal must use a do-while loop to avoid infinite loops
  • Deletion requires updating the last node's pointer when deleting the head
  • Useful for applications requiring circular iteration

Conclusion

Circular linked lists provide continuous traversal capabilities and eliminate null pointer handling. They're particularly useful for round-robin algorithms and applications requiring cyclic data structures.

Updated on: 2026-03-15T23:18:59+05:30

580 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements