Check Circular Linked List
#include <bits/stdc++.h> // Common includesusing namespace std; // Standard namespace
// Node Class: Defines structure of a linked list nodeclass Node {public: int data; // Data storage Node* next; // Pointer to next node
// Node Constructor Node(int data) { this->data = data; this->next = NULL; // Initialize next as NULL }};
// printList: Prints all elements in the listvoid printList(Node* head) { if(head == NULL) { cout << "List is Empty!" << endl; return; }
cout << "Singly List : "; while(head != NULL) { cout << head->data << " "; // Print data head = head->next; // Move to next node } cout << endl;}
// insertAtHead: Adds node to the beginningvoid insertAtHead(Node* &head, int data) { Node *temp = new Node(data); // Create new node temp->next = head; // New node points to old head head = temp; // Head updates to new node}
// insertAtTail: Adds node to the endvoid insertAtTail(Node* &tail, int data) { Node *temp = new Node(data); // Create new node tail->next = temp; // Old tail points to new node tail = temp; // Tail updates to new node}
// insertAtMiddle: Inserts node at a specific positionvoid insertAtMiddle(Node* &head, Node* &tail, int data, int pos) { if(pos == 1) { // Special case: insert at head insertAtHead(head, data); return; }
Node *temp = head; // Traverse pointer while(temp != NULL && pos > 2) { // Find node BEFORE insertion point temp = temp->next; pos--; }
if(temp==NULL || pos<=0) { // Invalid position check cout << "Invalid Position!" << endl; return; }
Node *insertNode = new Node(data); // Create node to insert insertNode->next = temp->next; // New node points to temp's next temp->next = insertNode; // Temp points to new node
if(insertNode->next == NULL) { // Update tail if inserted at end tail = insertNode; }}
// deletePosition: Deletes node at a specific positionvoid deletePosition(Node* &head, int pos) { Node *temp = head; // Pointer for deletion/traversal if(pos == 1) { // Special case: delete head head = head->next; delete temp; // Free memory return; }
while(temp!=NULL && pos > 2) { // Find node BEFORE deletion point temp = temp->next; pos--; }
if(temp==NULL || temp->next==NULL || pos<=0) { // Invalid position check cout << "Invalid Position!" << endl; return; }
Node* target = temp->next; // Node to be deleted temp->next = target->next; // Bypass target node delete target; // Free memory}
// deleteValue: Deletes first occurrence of a specific valuevoid deleteValue(Node* &head, int val) { Node* temp = head->next; // Current pointer Node* prev = head; // Previous pointer
if(head->data == val) { // Special case: delete head by value head = head->next; delete prev; // Free old head return; }
// Traverse to find the value while(temp!=NULL) { if(temp->data == val) { val = INT_MIN; // Sentinel to mark value found break; } prev = temp; // Move prev temp = temp->next; // Move temp }
if(prev->next==NULL || val!=INT_MIN) { // Value not found cout << "Value Not Found!" << endl; return; }
prev->next = temp->next; // Bypass target node delete temp; // Free memory}
// isCircular: Checks if the linked list is circularbool isCircular(Node* head) { if(head == NULL) { // Empty list is considered circular (or trivial case) return true; }
Node* temp = head->next; // Start from the second node
// Traverse until temp hits head (circular) or NULL (not circular) while(temp != head) { if(temp == NULL) { // Reached end of list, not circular return false; } temp = temp->next; // Move to next node }
return true; // Loop completed, temp is head, so it's circular}
// main: Program entry point, demonstrates operationsint main() { Node *head = new Node(1); // Create initial node Node *tail = head; // Tail points to head initially
// Build list: 1 -> 2 -> 4 -> 8 -> 16 -> 32 for(int i=1; i<=5; i++) { insertAtTail(tail, pow(2,i)); } printList(head); // Print original list
// Uncomment the line below to make it circular for testing: // tail->next = head; // Makes the list circular
// Check if the list is circular if(isCircular(head)) { cout << "Circular List!" << endl; } else { cout << "Not a Circular List!" << endl; }
return 0; // Indicate success}
Understood! Here’s the complete revision guide in Markdown format, ready for you to copy and use.
1. What is it?
- A linear data structure where elements are stored in nodes.
- Each node has:
data
(the actual value)next
(a pointer to the next node).
- The last node’s
next
pointer isNULL
. - Accessed via a
head
pointer (first node) and sometimes atail
pointer (last node for efficiency).
2. Core Node
Structure
class Node {public: int data; // The value Node* next; // Points to the next node Node(int data) { this->data = data; this->next = NULL; }};
- Key:
Node* next
is what links everything together.
3. Basic Operations (Quick Glance)
-
printList(Node* head)
:- Purpose: Traverse and display all elements.
- How: Start at
head
, loopwhile (head != NULL)
, printhead->data
, thenhead = head->next;
. - Edge Case: If
head == NULL
, list is empty. - Example:
1->2->3
prints “Singly List : 1 2 3”
-
insertAtHead(Node* &head, int data)
:- Purpose: Add a new node at the beginning.
- How: 1. Create new node. 2. New node’s
next
points to oldhead
. 3.head
becomes new node. - Key:
head
is passed by reference (&
). - Example:
2->3
+insertAtHead(head, 1)
→1->2->3
-
insertAtTail(Node* &tail, int data)
:- Purpose: Add a new node at the end.
- How: 1. Create new node. 2. Old
tail
’snext
points to new node. 3.tail
becomes new node. - Key:
tail
is passed by reference (&
). - Example:
1->2
+insertAtTail(tail, 3)
→1->2->3
-
insertAtMiddle(Node* &head, Node* &tail, int data, int pos)
:- Purpose: Insert at a specific
pos
. - How:
- Handle
pos=1
(callinsertAtHead
). - Else, traverse (
temp
) to node beforepos
. - Insert: New node’s
next
totemp->next
,temp->next
to new node. - Update
tail
if new node is last.
- Handle
- Example:
10->20->40
+insertAtMiddle(..., 30, 3)
→10->20->30->40
- Purpose: Insert at a specific
-
deletePosition(Node* &head, int pos)
:- Purpose: Delete node at specific
pos
. - How:
- Handle
pos=1
(updatehead
,delete
old head). - Else, traverse (
temp
) to node beforepos
. - Bypass target node (
temp->next = target->next
),delete
target.
- Handle
- Example:
10->20->30
+deletePosition(head, 2)
→10->30
- Purpose: Delete node at specific
-
deleteValue(Node* &head, int val)
:- Purpose: Delete the first occurrence of
val
. - How:
- Handle
head->data == val
(updatehead
,delete
old head). - Else, use
prev
andtemp
to findval
. - Bypass
temp
(prev->next = temp->next
),delete
temp
.
- Handle
- Example:
10->20->30
+deleteValue(head, 20)
→10->30
- Purpose: Delete the first occurrence of
4. Advanced Operation: reverseInGroup(Node* head, int k)
-
Purpose: Reverses the linked list in groups of
k
nodes. -
Approach: Recursive.
-
How it works (Step-by-Step for each
k
-group):- Reverse First K Nodes (Iterative):
- Use
prev
,curr
,next
pointers. - Loop
k
times:next = curr->next; curr->next = prev; prev = curr; curr = next;
- Use
- Recursive Call:
- If
next
(start of next group) is notNULL
, link the originalhead
(which is now the tail of the reversed group) to the result ofreverseInGroup(next, k)
.
- If
- Return New Head: Return
prev
(the new head of the currentk
-group).
- Reverse First K Nodes (Iterative):
-
Example: Initial:
1 -> 2 -> 3 -> 4 -> 5 -> 6
,k = 3
- Call 1 (
reverseInGroup(1, 3)
):- Reverses
1->2->3
into3<-2<-1
.prev
is3
,curr
is4
. 1->next
(original head) is set toreverseInGroup(4, 3)
.
- Reverses
- Call 2 (
reverseInGroup(4, 3)
):- Reverses
4->5->6
into6<-5<-4
.prev
is6
,curr
isNULL
. - Returns
6
.
- Reverses
- Back to Call 1:
1->next
becomes6
. - Final Return: Call 1 returns
3
. - Result:
3 -> 2 -> 1 -> 6 -> 5 -> 4
- Call 1 (
5. isCircular(Node* head)
Function (New!)
-
Purpose: Determine if a singly linked list forms a cycle.
-
Concept: In a circular list, traversing from any node eventually returns to a previously visited node (specifically,
head
in this implementation’s logic). In a non-circular list, you reachNULL
. -
How it works (Step-by-Step):
- Empty List Check:
if(head == NULL)
: Returnstrue
(empty list can be considered trivially circular).
- Initialize Traversal Pointer:
Node* temp = head->next;
- Start
temp
from the second node.
- Traverse and Check:
while(temp != head)
: Keep movingtemp
until it either hitshead
orNULL
.- Inside Loop:
if(temp == NULL)
: Iftemp
becomesNULL
, we reached the end.- Return
false
(not circular).
- Return
temp = temp->next;
: Movetemp
to the next node.
- Circular Confirmation:
- If the loop finishes (
temp == head
), it meanstemp
started athead->next
and eventually came back tohead
. - Return
true
(it’s circular).
- If the loop finishes (
- Empty List Check:
-
Example:
Scenario 1: Non-Circular List
head -> 1 -> 2 -> 3 -> NULL
temp
starts at2
.temp
moves:2
→3
→NULL
.- When
temp
isNULL
,if(temp == NULL)
is true. Returnsfalse
.
Scenario 2: Circular List
head -> 1 -> 2 -> 3 -> (points back to 1)
(aftertail->next = head;
is uncommented)temp
starts at2
.temp
moves:2
→3
→1
.- When
temp
is1
,while(temp != head)
condition (1 != 1
) becomes false, loop ends. - Returns
true
.
6. main()
Function
- Purpose: Test and demonstrate.
- Flow:
- Creates initial
Node
(head
). - Populates list using
insertAtTail
. - Prints the original list.
- (Optional: Uncomment
tail->next = head;
to make it circular). - Calls
isCircular
to check its nature. - Prints the result (
"Circular List!"
or"Not a Circular List!"
).
- Creates initial