Visual walkthrough — STL containers — vector, list, deque, array, set, multiset, map, multimap, unordered_map, unordered_set
5.2.19 · D2· Coding › C++ Programming › STL containers — vector, list, deque, array, set, multiset,
Hum parent note ki central formula earn karne wale hain: ek picture at a time. Agar in symbols mein se koi abhi scary lag raha hai — good. Step 8 tak woh obvious feel hone lagenge.
Step 1 — Memory mein ek vector actually hota kya hai
KYA HAI. Ek std::vector teen numbers ka wrapper hai: memory ke ek block ki taraf ek pointer, ek size (kitne slots use ho rahe hain), aur ek capacity (block kitne slots hold kar sakta hai fill hone se pehle).
KYUN. Jab tak tum yeh nahi dekh sakte ki "full" ka matlab kya hai, tab tak tum kisi cheez ko grow karne ki cost ke baare mein reason nahi kar sakte. Poora argument size aur capacity ke beech ke gap par hinge karta hai.
PICTURE. Neeche, grey slots reserved but empty hain (capacity abhi use nahi hui); cyan slots occupied hain (size). Notice karo: push_back sirf agli grey slot mein likhta hai aur size ko ek se bump karta hai. Yeh ek single write hai — — jab tak koi grey slot maujood hai.

Step 2 — Sasta case aur mehnga case
KYA HAI. Jab tum push_back call karte ho, exactly do cheezein ho sakti hain:
- Sasta (): ek free slot mein likho, . Constant kaam.
- Mehnga (): jagah nahi — ek bada block allocate karo, saare purane elements copy karo, purana block free karo, phir likho. Yeh copy kaam hai.
KYUN. Agar har push mehnga hota, toh vector ek bekar container hota. Magic yeh hai ki mehnga case rare hai. Yeh measure karne ke liye ki "kitna rare", pehle hume yeh fix karna hoga ki naya block kitna bada hoga.
PICTURE. Left: ek push jo free slot mein land kar raha hai (ek arrow, ek write). Right: ek full block jo reallocation force kar raha hai — har existing element ek naye, bade ghar mein carry ho raha hai.

Step 3 — Growth rule: doubling kyun?
KYA HAI. Full hone par, vector capacity ka block allocate karta hai (typical libstdc++/MSVC choice). Woh double karta hai.
Doubling kyun aur "+1 har baar" kyun nahi? Yeh key design decision hai, toh isko justify karte hain, assume nahi. Maan lo hum iske bajaye har baar fixed +1 se badhte. Toh har single push ek "full" push hota, saare elements copy karta: total copies — quadratic! Doubling ki wajah se full-events exponentially rarer ho jaate hain jaise vector grow karta hai, aur yahi ko mein turn karta hai.
PICTURE. Do timelines of "reallocation kab fire hoti hai?" The +1 strategy constantly fire karti hai; doubling strategy par fire karti hai — gaps har baar double hote hain.

Step 4 — Har expensive event list karo
KYA HAI. Empty vector se start karo aur elements push karo. Reallocations (copies) exactly tab hoti hain jab size hit kare, jahan sabse bada power of two hai jo ho.
KYUN. Total cost add up karne ke liye, pehle hume har expensive moment aur uski cost enumerate karni hogi. Capacity par ek reallocation exactly elements copy karti hai (pura existing block carry karta hai).
PICTURE. Pushes ki ek number line. Amber spikes reallocations mark karti hain; har spike apni copy cost ke saath labelled hai (). Spikes ke beech sab kuch cheap pushes ka flat run hai.

Step 5 — Copy work sum karo (geometric series)
KYA HAI. Saari reallocations mein total copy work:
Yeh tool kyun — geometric sum? Har term pehle wale se double hai (constant ratio ). Ek sum jahan har term ek fixed number se multiply hoti hai ek geometric series hai, aur uski ek famously clean closed form hoti hai. Hum isko exactly isliye use karte hain kyunki "har reallocation pichle se double copy karti hai" ek doubling pattern hai — geometric series exactly isi shape ko collapse karne ke liye bani thi.
PICTURE. Classic proof-without-words: heights ke bars stack karo. Poora stack agले bar se ek short hai. Woh single missing unit hi closed form ka poora content hai.

Step 6 — Ise se bound karo
KYA HAI. Abstract ko ke terms mein kuch se replace karo:
KYUN. Humne define kiya tha taaki ho (Step 4). Dono sides ko 2 se multiply karo: . Aur drop karne se left side aur badi ho jaati hai, toh strict inequality hold karti hai. Yeh "sum over reallocations" ko ek plain bound mein convert karta hai jo reader feel kar sake: saari copying milake se do guna se kam hai.
PICTURE. Do bars side by side: total copy work , aur ceiling . kabhi ceiling ko touch nahi karta, chahe kitna bhi bada ho.

Step 7 — Divide karo: amortised cost
KYA HAI. Amortised analysis poochta hai: "total cost ko saare operations mein evenly spread karo, toh har ek ko average par kya cost aati hai?"
Divide kyun? Amortised ka matlab yeh nahi ki "har push sasta hai" — ek push (reallocation) sach mein ka hota hai. Iska matlab yeh hai ki poore sequence mein bill split constant hai. Total ko count se divide karna exactly wahi split hai.
PICTURE. True per-push cost ki ek jagged red line (mostly height 1 par, powers of two par tall spikes ke saath) aur height par ek flat amber line — average. Spikes flat line ke upar jaati hain lekin calm valleys average ko neeche kheench laati hain.

Step 8 — Degenerate aur edge cases
KYA AUR KYUN. Ek derivation tab tak finish nahi hoti jab tak har corner cover na ho.
- (empty): koi pushes nahi, koi reallocations nahi, . Formula deta hai jo ek empty/undefined sum hai — hum ise simply treat karte hain. Koi contradiction nahi: zero kaam zero pushes ke liye.
- (single push): , ek reallocation element copy karti hai... actually ek fresh empty vector mein pehla push allocate karta hai lekin copy kuch nahi karta (copy karne ke liye kuch hai hi nahi). Toh real implementations bound se bhi better karti hain — bound ek upper limit hai, kabhi violate nahi hoti.
- Pehle
reserve(n): agar tum vector ko uski final size pehle se bata do, toh woh ek baar allocate karta hai aur har push cheap branch mein hoti hai — zero reallocations. Yahi fix hai jo parent note ki mistake box point out karti hai. - Growth factor (e.g. kuch libraries mein ): ratio phir bhi geometric series deta hai , phir bhi total, phir bhi amortised. Koi bhi constant factor kaam karta hai — sirf "+1 growth" (ratio effectively ) isko wapas mein todta hai.
PICTURE. Char mini-panels: empty, single push, pre-reserved (flat, koi spikes nahi), aur growth (spikes paas paas lekin phir bhi exponentially sparse).

Ek-picture summary
Upar sab kuch compress: per-push cost curve (powers of two par spikes), running total se bounded ek line par chadh raha hai, aur flat amortised average — sab ek blueprint par.

Recall Feynman retelling — jaise kisi dost ko explain karo
Vector ek box hai jisme spare room hai. Koi cheez add karna usually free hai — tum use spare slot mein drop kar dete ho. Lekin jab box full ho jaata hai, tum ek double size ka box khareedne aur sab kuch carry karne par majboor ho. Woh carrying slow hai. Trick yeh hai: kyunki tum double karte ho har baar, box utna half frequently bharta hai jitna pichli baar grow kiya tha — slow moves rarer aur rarer hote jaate hain. Agar tum saari carrying jo tumne kabhi ki sab add karo, toh woh tumhari stored cheezein ki sankhya se do guna se kam hai. Woh bill har "add" mein split karo, aur har add average par ek tiny constant cost karta hai. Iska matlab yahi hai "amortised ": rare expensive moves, cheap ones ki bheed ke dwara pay ki gayi. Aur agar size pehle se pata tha, toh reserve karo — phir tumhe kuch carry hi nahi karna padega.
Recall Quick self-test
"+1" se har baar grow karne par total kyun hota hai? ::: Har push ek "full" push hota jo saare elements copy karta, toh total .
kya hai aur yahan iska kya matlab hai? ::: — 100 elements tak pahunchne se pehle aakhri reallocation ne items copy kiye.
Ek single push_back worst case kya complexity hai? ::: — jab woh reallocation trigger karta hai aur poora array copy karta hai.
ki closed form? ::: .
Jab size pata ho toh saari reallocations kaise avoid karo? ::: Pehle reserve(n) call karo.
Prerequisites revisited: Amortised analysis, Big-O notation, aur Cache locality se memory-layout intuition — yeh sab is result ko feed karte hain. Parent par wapas: STL containers overview.