Linked Lists: Singly, Doubly, Circular
লিংকড লিস্ট — singly, doubly, circular
1. Why Linked Lists?
An array gives you O(1) random access but O(n) insertion in the middle. A linked list flips this trade-off: insertion at any known position is O(1), but accessing the i-th element costs O(i). Each node holds data and a pointer to the next node — like train coaches connected by hooks rather than welded together.
2. Three Flavours — Singly, Doubly, Circular
Singly linked: each node points to the next. Simple, low memory, but cannot walk backwards.
Doubly linked: each node has next and prev — used by browsers' back/forward stacks and by std::list.
Circular linked: the last node points back to the first — useful for round-robin schedulers and music playlists on shuffle-loop.
next ও prev দুটোই থাকে — browser-এর back/forward এবং std::list এতেই বানানো। Circular: শেষ node ঘুরে প্রথম node-কে ধরে — round-robin scheduling এবং music playlist-এর shuffle-loop-এ চমৎকার কাজ করে।
3. Demo 1 — A Full Singly Linked List
#include <bits/stdc++.h>
using namespace std;
struct Node {
int data;
Node* next;
Node(int x) : data(x), next(nullptr) {}
};
struct List {
Node* head = nullptr;
void push_front(int x) {
Node* n = new Node(x);
n->next = head;
head = n;
}
void push_back(int x) {
Node* n = new Node(x);
if (!head) { head = n; return; }
Node* cur = head;
while (cur->next) cur = cur->next;
cur->next = n;
}
void print() {
for (Node* c = head; c; c = c->next) cout << c->data << " -> ";
cout << "NULL\n";
}
};
int main() {
List L;
L.push_back(10); L.push_back(20); L.push_back(30);
L.push_front(5);
L.print();
return 0;
}
4. Demo 2 — The Three-Pointer Reverse & Floyd's Cycle Detection
Reversing a singly linked list iteratively requires three pointers — prev,
cur, and nxt — moving forward together. Floyd's tortoise &
hare uses two pointers moving at different speeds to detect cycles in O(n) time, O(1) space.
prev, cur, nxt — একসাথে এগোয়। Floyd's tortoise & hare: একটি pointer এক ধাপ, আরেকটি দুই ধাপ চলে। যদি কোথাও মিলে যায়, cycle আছে — O(n) সময়, O(1) space।
#include <bits/stdc++.h>
using namespace std;
struct Node { int data; Node* next; Node(int x):data(x),next(nullptr){} };
Node* reverse(Node* head) {
Node *prev = nullptr, *cur = head;
while (cur) {
Node* nxt = cur->next;
cur->next = prev;
prev = cur;
cur = nxt;
}
return prev;
}
bool hasCycle(Node* head) {
Node *slow = head, *fast = head;
while (fast && fast->next) {
slow = slow->next;
fast = fast->next->next;
if (slow == fast) return true;
}
return false;
}
int main() {
Node* h = new Node(1);
h->next = new Node(2);
h->next->next = new Node(3);
h->next->next->next = new Node(4);
h = reverse(h);
for (Node* c = h; c; c = c->next) cout << c->data << " ";
cout << "\nCycle? " << hasCycle(h) << "\n";
return 0;
}
5. Array vs Linked List — When to Use Which?
| Operation | Array / Vector | Linked List |
|---|---|---|
Random access a[i] | O(1) | O(i) |
| Insert at front | O(n) | O(1) |
| Insert at back | amortised O(1) | O(1) (with tail ptr) |
| Insert at known node | O(n) | O(1) |
| Memory overhead | low | 2 pointers per node |
| Cache friendliness | excellent | poor (pointer chase) |
std::list + std::unordered_map).
6. Sneak Peek — LRU Cache
An LRU (Least Recently Used) cache evicts the oldest unused item when full. Implemented with a doubly linked list (for O(1) move-to-front) plus a hash map (for O(1) lookup). Browsers, databases, and bKash session caches all use this idea.
7. Practice Problems
-
Find the middle node of a linked list (for even count, return the second middle).Linked list-এর মাঝের node বের করুন (even হলে দ্বিতীয় middle)।
✨ Show Answer (উত্তর দেখুন)
ans1.cpp#include <bits/stdc++.h> using namespace std; struct N{int v;N* nx;N(int x):v(x),nx(nullptr){}}; int main() { N* h = new N(1); N* t = h; for (int i = 2; i <= 6; i++) { t->nx = new N(i); t = t->nx; } N *s = h, *f = h; while (f && f->nx) { s = s->nx; f = f->nx->nx; } cout << s->v << "\n"; } -
Merge two sorted linked lists into one sorted list.দুটি sorted linked list merge করে একটি sorted list বানান।
✨ Show Answer (উত্তর দেখুন)
ans2.cpp#include <bits/stdc++.h> using namespace std; struct N{int v;N* nx;N(int x):v(x),nx(nullptr){}}; N* build(vector<int> a){N d(0);N* t=&d;for(int x:a){t->nx=new N(x);t=t->nx;}return d.nx;} int main() { N* a = build({1,3,5}); N* b = build({2,4,6,8}); N dum(0); N* t = &dum; while (a && b) { if (a->v <= b->v) { t->nx = a; a = a->nx; } else { t->nx = b; b = b->nx; } t = t->nx; } t->nx = a ? a : b; for (N* c = dum.nx; c; c = c->nx) cout << c->v << " "; cout << "\n"; } -
Detect a cycle and return the node where the cycle begins.Cycle detect করে যেই node থেকে cycle শুরু সেটিকে return করুন।
✨ Show Answer (উত্তর দেখুন)
ans3.cpp#include <bits/stdc++.h> using namespace std; struct N{int v;N* nx;N(int x):v(x),nx(nullptr){}}; int main() { N* a = new N(1); N* b = new N(2); N* c = new N(3); N* d = new N(4); a->nx = b; b->nx = c; c->nx = d; d->nx = b; // cycle starts at b N *s = a, *f = a; while (f && f->nx) { s = s->nx; f = f->nx->nx; if (s == f) break; } if (!f || !f->nx) { cout << "no cycle\n"; return 0; } s = a; while (s != f) { s = s->nx; f = f->nx; } cout << "cycle starts at " << s->v << "\n"; } -
Remove duplicates from a sorted linked list.Sorted linked list থেকে duplicate সরিয়ে দিন।
✨ Show Answer (উত্তর দেখুন)
ans4.cpp#include <bits/stdc++.h> using namespace std; struct N{int v;N* nx;N(int x):v(x),nx(nullptr){}}; int main() { N d(0); N* t = &d; for (int x : {1,1,2,3,3,4,5,5}) { t->nx = new N(x); t = t->nx; } for (N* c = d.nx; c && c->nx; ) { if (c->v == c->nx->v) c->nx = c->nx->nx; else c = c->nx; } for (N* c = d.nx; c; c = c->nx) cout << c->v << " "; cout << "\n"; } -
Reverse a linked list in groups of size k.Linked list-কে k size-এর group-এ reverse করুন।
✨ Show Answer (উত্তর দেখুন)
ans5.cpp#include <bits/stdc++.h> using namespace std; struct N{int v;N* nx;N(int x):v(x),nx(nullptr){}}; N* revK(N* h, int k) { N* c = h; int cnt = 0; while (c && cnt < k) { c = c->nx; cnt++; } if (cnt < k) return h; N *prev = revK(c, k), *cur = h; for (int i = 0; i < k; i++) { N* nx = cur->nx; cur->nx = prev; prev = cur; cur = nx; } return prev; } int main() { N d(0); N* t = &d; for (int i = 1; i <= 7; i++) { t->nx = new N(i); t = t->nx; } N* h = revK(d.nx, 3); for (N* c = h; c; c = c->nx) cout << c->v << " "; cout << "\n"; } -
Check if a linked list is a palindrome (O(n) time, O(1) space using reverse-half).Linked list palindrome কিনা — half reverse করে O(n) সময় ও O(1) space-এ যাচাই করুন।
✨ Show Answer (উত্তর দেখুন)
ans6.cpp#include <bits/stdc++.h> using namespace std; struct N{int v;N* nx;N(int x):v(x),nx(nullptr){}}; N* rev(N* h){N* p=nullptr;while(h){N* n=h->nx;h->nx=p;p=h;h=n;}return p;} int main() { N d(0); N* t = &d; for (int x : {1,2,3,2,1}) { t->nx = new N(x); t = t->nx; } N *s = d.nx, *f = d.nx; while (f && f->nx) { s = s->nx; f = f->nx->nx; } N* r = rev(s); N* a = d.nx; bool ok = true; while (r) { if (a->v != r->v) { ok = false; break; } a = a->nx; r = r->nx; } cout << (ok ? "YES" : "NO") << "\n"; } -
Find intersection node of two linked lists (Y-shape).দুটি linked list-এর intersection node বের করুন (Y-shape)।
✨ Show Answer (উত্তর দেখুন)
ans7.cpp#include <bits/stdc++.h> using namespace std; struct N{int v;N* nx;N(int x):v(x),nx(nullptr){}}; int main() { N* common = new N(8); common->nx = new N(9); N* A = new N(1); A->nx = new N(2); A->nx->nx = common; N* B = new N(5); B->nx = common; N *a = A, *b = B; while (a != b) { a = a ? a->nx : B; b = b ? b->nx : A; } cout << (a ? a->v : -1) << "\n"; } -
Remove the n-th node from the end of a linked list in one pass.Linked list-এর শেষ থেকে n-তম node এক pass-এ সরিয়ে দিন।
✨ Show Answer (উত্তর দেখুন)
ans8.cpp#include <bits/stdc++.h> using namespace std; struct N{int v;N* nx;N(int x):v(x),nx(nullptr){}}; int main() { N d(0); N* t = &d; for (int i = 1; i <= 5; i++) { t->nx = new N(i); t = t->nx; } int n = 2; N *fast = &d, *slow = &d; for (int i = 0; i <= n; i++) fast = fast->nx; while (fast) { fast = fast->nx; slow = slow->nx; } slow->nx = slow->nx->nx; for (N* c = d.nx; c; c = c->nx) cout << c->v << " "; cout << "\n"; }
Summary — Module 08
Linked lists trade O(1) random access for O(1) insertion at known nodes. Singly is the simplest;
doubly enables backward walk; circular powers round-robin schedules. The three-pointer reverse and
Floyd's tortoise-and-hare cycle detection are essential techniques for ICPC and FAANG interviews.
Use std::list in production; reach for raw nodes only when you need to learn or to build something special like LRU.
std::list ব্যবহার করুন; raw node শুধু শিখতে বা LRU-র মতো বিশেষ কিছু বানাতে।