CLL vs SLL, Use of Tail Pointer
A singly linked list (SLL) is usually drawn as an open chain: the last node’s next is NULL. A singly circular linked list (CLL) closes the chain so the last node points back (typically to head). This page compares the two and explains why many CLL implementations keep a tail pointer—not just head—to reach both ends in O(1).
- SLL vs CLL — last link, traversal, when each fits
- Tail pointer in SLL (append and limits)
- Tail pointer in CLL —
tail->next == headidiom - Quick comparison table and key takeaway
1) SLL vs CLL — structure
Both use the same node shape (data + next). The difference is what the last node points to:
- SLL (linear): last node’s
nextisNULL. You detect the end byNULL. - CLL (circular): in a non-empty list, last node’s
nextpoints into the list—almost always head. There is noNULL“end marker” on the last node.
Diagrams (same values 10 → 20 → 30)
SLL — open chain CLL — ring (last → head)
head tail often stored here
│ │
▼ ▼
┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐
│ 10 │──→│ 20 │──→│ 30 │──→ NULL │ 10 │←──│ 30 │←──│ 20 │…
└──────┘ └──────┘ └──────┘ └──┬───┘ └──────┘ └──────┘
▲ head head ───┘ ▲_______________│
└── tail→next = head
2) SLL vs CLL — traversal and operations
| Topic | SLL | CLL |
|---|---|---|
| End of list | NULL after last node |
No NULL on last; must stop by count or “back to start” |
| Typical forward walk | while (cur != NULL) |
Need a different stop condition (infinite loop if careless) |
| Insert at front | O(1) with head |
O(1) if you can update last’s next when only head changed—or use tail (see below) |
| Insert at end | O(n) with only head; O(1) with tail |
With tail + tail->next == head: append often O(1) |
| “Natural” wrap-around | Not built in | Round-robin / cyclic iteration |
Choose SLL when you want a simple NULL-terminated walk and a clear end. Choose CLL when the problem is cyclic or you want uniform “always a next node” inside a non-empty list.
3) Tail pointer in SLL
If you only store struct Node *head, inserting or deleting at the end requires walking to the last node — O(n). Maintaining an extra struct Node *tail lets you append in O(1) by linking the old last node to the new node and moving tail.
Limits: after some deletes you must keep tail correct. Insert/delete at the end still needs the predecessor of the last node if you only have singly links—so “delete last” is still awkward without a full walk or a doubly linked list.
4) Tail pointer in CLL — why it shines
A very common CLL convention is:
tailpoints to the last node in the ring.tail->nextis always head (first node).
Then in O(1) time you have:
- Last node:
tail - First node:
tail->next(i.e.head)
That makes insert at end straightforward: create a new node, link old tail->next through the new node, update tail, and keep tail->next == head. Insert at beginning can also be done in O(1) with the same invariant: new node’s next becomes the old first node; tail->next points to the new first; advance nothing on tail if the new node is before the old head (implementation details vary—some APIs expose only tail).
Without tail, only head: finding the last node still costs O(n) in a CLL because you must walk until you are about to return to head.
Conceptual variables in C
struct Node {
int data;
struct Node *next;
};
/* Common CLL pattern: one pointer to last node */
struct Node *tail; /* tail->next is the first node (head) */
/* "head" is then: tail->next (when list non-empty) */
Empty list: usually tail == NULL (and no nodes). Single node: that node’s next points to itself; tail points at that node.
5) Summary
- SLL — open chain,
NULLterminator, simple loops; tail helps append only. - CLL — closed ring; traversal needs explicit stopping; tail + tail→next == head gives O(1) access to both first and last.
Key takeaway
The big win for a tail pointer in CLL is the invariant tail->next == head: one pointer variable gives you the last and the first node immediately. In a plain SLL, a tail only fixes append; in CLL it also aligns with how the ring closes.
See also: CLL Introduction · Insert at Beginning (CLL) · Insert at End (SLL) · Types of Linked List