Topic 3

Circular Linked List

Circular vs Singly โ€” The Key Difference

The last node points back to head instead of NULL.

Critical code differences:
โ€ข Empty single node: head->next == head (not NULL)
โ€ข Traversal: while(temp->next != head)
โ€ข Display: Uses do-while loop
โ€ข Insert at beginning: Must also update last node's next

Circular Linked List

head
9
โ†’
2
โ†’
7
โ†’
1
โ†’
3
โ†ป head

Singly vs Circular โ€” Critical Differences

AspectSingly LLCircular LL
Last node points toNULLhead
Traversal conditiontemp != NULLtemp->next != head
Display loopwhile loopdo-while loop
Single node checkhead->next == NULLhead->next == head
Empty list, first addnewNode->next = NULLnewNode->next = newNode
Insert at beginningJust update headUpdate head + last->next
Delete from beginningMove head forwardMove head + update last->next
complete-circular-linked-list
#include <iostream>
using namespace std;

class Node {
public:
    int data;
    Node* next;
};

class LinkedList {
private:
    Node* head;

public:
    LinkedList() {
        head = NULL;
    }

    // Insert at beginning
    void insert(int new_data) {
        Node* new_node = new Node();
        new_node->data = new_data;

        if (head == NULL) {
            // If list is empty, node points to itself
            new_node->next = new_node;
            head = new_node;
        } else {
            Node* temp = head;
            // Traverse to last node
            while (temp->next != head) {
                temp = temp->next;
            }
            // Insert at beginning, update last->next
            temp->next = new_node;
            new_node->next = head;
            head = new_node;
        }
    }

    // Insert at specific position
    void insertAtSpecificPosition(int new_data, int position) {
        Node* new_node = new Node();
        new_node->data = new_data;

        if (head == NULL) {
            cout << "List is empty, inserting at beginning." << endl;
            new_node->next = new_node;
            head = new_node;
            return;
        }

        if (position == 0) {
            insert(new_data);
            return;
        }

        Node* temp = head;
        for (int i = 0; i < position - 1 && temp->next != head; i++) {
            temp = temp->next;
        }

        new_node->next = temp->next;
        temp->next = new_node;
    }

    // Insert at end
    void insertAtEnd(int new_data) {
        Node* new_node = new Node();
        new_node->data = new_data;

        if (head == NULL) {
            new_node->next = new_node;
            head = new_node;
            return;
        }

        Node* temp = head;
        while (temp->next != head) {
            temp = temp->next;
        }

        temp->next = new_node;
        new_node->next = head;
    }

    // Delete from beginning
    void deleteFromBeginning() {
        if (head == NULL) {
            cout << "List is empty." << endl;
            return;
        }

        Node* temp = head;

        // If only one node
        if (head->next == head) {
            delete head;
            head = NULL;
            return;
        }

        // Find last node
        while (temp->next != head) {
            temp = temp->next;
        }

        Node* toDelete = head;
        head = head->next;
        temp->next = head;   // Maintain circular link
        delete toDelete;
    }

    // Delete from specific position
    void deleteFromSpecificPosition(int position) {
        if (head == NULL) {
            cout << "List is empty." << endl;
            return;
        }

        if (position == 0) {
            deleteFromBeginning();
            return;
        }

        Node* temp = head;
        Node* prev = NULL;

        for (int i = 0; i < position && temp->next != head; i++) {
            prev = temp;
            temp = temp->next;
        }

        prev->next = temp->next;
        delete temp;
    }

    // Delete from end
    void deleteFromEnd() {
        if (head == NULL) {
            cout << "List is empty." << endl;
            return;
        }

        Node* temp = head;
        Node* prev = NULL;

        // If only one node
        if (head->next == head) {
            delete head;
            head = NULL;
            return;
        }

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

        prev->next = head;
        delete temp;
    }

    // Display (uses do-while!)
    void display() {
        if (head == NULL) {
            cout << "The list is empty." << endl;
            return;
        }

        Node* temp = head;
        cout << "Circular LL: ";
        do {
            cout << temp->data << " ";
            temp = temp->next;
        } while (temp != head);
        cout << endl;
    }
};

int main() {
    LinkedList l;

    l.insert(3);
    l.insert(1);
    l.insert(7);
    l.insert(2);
    l.insert(9);
    l.display();

    l.insertAtSpecificPosition(5, 2);
    l.display();

    l.insertAtEnd(10);
    l.display();

    l.deleteFromBeginning();
    l.display();

    l.deleteFromSpecificPosition(2);
    l.display();

    l.deleteFromEnd();
    l.display();

    return 0;
}