3.2.1Linear Data Structures

Array — static, dynamic; cache locality; amortized O(1) append

2,137 words10 min readdifficulty · medium

1. What is an array?

WHY contiguous? So we never store where the next element is — we compute it.


2. Static vs Dynamic arrays

The key trick: a dynamic array stores two numbers:

Term Meaning
size how many elements you've actually put in
capacity how many slots are allocated right now (capacity ≥ size)

3. The append operation & amortized O(1)

WHAT happens on append(x):

  1. If size < capacity: write x at index size, do size++. → O(1) (cheap append).
  2. If size == capacity: allocate a new block of capacity gcapacityg\cdot \text{capacity}, copy all size old elements, free old block, then write. → O(n) (expensive append).

Derivation: why doubling gives amortized O(1)


4. Cache locality — the hidden superpower

Figure — Array — static, dynamic; cache locality; amortized O(1) append

5. Complexity summary (the 80/20 table)

Operation Static array Dynamic array
Access a[i] O(1) O(1)
Update a[i]=x O(1) O(1)
Append at end n/a O(1) amortized (O(n) worst)
Insert/delete at front/middle O(n) (shift) O(n) (shift)
Search (unsorted) O(n) O(n)
Space O(n) O(n), up to ~2× over-allocated

Recall Feynman: explain to a 12-year-old

Imagine a row of identical lockers numbered 0,1,2… To open locker 5 you just walk straight to it — you don't open lockers 0–4 first. That's why arrays are instant to read. Now suppose the row is full and you want one more locker. You can't glue one onto the end (the wall's there). So you build a new row twice as long, carry all your stuff over, and keep going. Doing this doubling trick means you only move stuff occasionally, so on average adding a locker is still cheap. Bonus: because the lockers are in one straight line, when you grab from locker 5 your hands are already near 6,7,8 — the computer "grabs a handful at once." Scattered lockers (linked list) would make you run back and forth.


Flashcards

What single property of arrays gives O(1) access AND cache locality?
Contiguous memory layout with fixed-size elements.
Derive the address formula for element i.
addr(i) = B + i·s, where B = base address, s = element size in bytes. Element i+1 starts s bytes after i, so by induction add i·s.
Why is dynamic-array append O(1) amortized not O(1) worst-case?
Most appends just write (O(1)); occasionally a full array triggers an O(n) copy. Averaged over n appends the total copy cost is O(n), so per-append is O(1).
What two numbers does a dynamic array track and how do they relate?
size (elements used) and capacity (slots allocated), with capacity ≥ size.
Total copy cost of n appends with doubling growth?
1+2+4+…+2^k < 2n = O(n), so O(1) amortized.
Why does growing by a constant (+1) make append O(n) amortized?
Every append resizes; total copies = 1+2+…+(n-1) = n(n-1)/2 = O(n²); divided by n gives O(n).
What is a cache line and why do arrays exploit it?
A ~64-byte chunk the CPU loads at once; contiguous array elements ride in together, so neighbours are pre-loaded → fewer slow RAM trips.
For 64-byte lines and 4-byte ints, how many elements per fetch?
64/4 = 16 elements.
Cost of inserting at the front of an array?
O(n) — every element must shift one slot.
Static vs dynamic array key difference?
Static = fixed size at allocation; dynamic = can grow by reallocating a bigger block and copying.

Connections

  • Linked List — opposite trade-off: O(1) splice but poor cache locality, O(n) access.
  • Amortized Analysis — aggregate / accounting / potential methods generalize the doubling argument.
  • Geometric Series — the 2j<2n\sum 2^j < 2n bound underpinning O(1) append.
  • CPU Cache and Memory Hierarchy — why contiguity beats equal Big-O structures.
  • Hash Table — uses dynamic arrays (buckets) and the same doubling/rehash growth.
  • Stack (Data Structure) — typically implemented on a dynamic array; push = amortized O(1) append.
  • Big-O Notation — worst vs amortized vs average.

Concept Map

enables

enables

gives

gives

underlies

tracks

full triggers

costs O of n

averages to

Contiguous memory block

Same size elements

addr i = B + i·s

O(1) random access

Cache locality

Static array fixed size

Dynamic array grows at runtime

size and capacity

Resize copy on full

Geometric doubling growth

Amortized O(1) append

Hinglish (regional understanding)

Intuition Hinglish mein samjho

Dekho, array ka sabse bada raaz sirf ek hai: saara data memory me ek saath, lagataar (contiguous) rakha jaata hai, aur har element ka size same hota hai. Isi wajah se computer ko a[i] dhoondhne ke liye kahin search nahi karna padta — wo seedha formula laga deta hai: addr(i) = B + i·s, jahan B starting address aur s element ka size hai. Bas ek multiply aur ek add — isliye access O(1) hota hai, chahe array kitna bhi bada ho.

Ab dynamic array (jaise Python list, C++ vector, Java ArrayList) andar se ek static array hi hota hai, par usme do cheezein store hoti hain: size (kitne element daale) aur capacity (kitni jagah allocate hai). Jab size == capacity ho jaata hai aur tum naya element daalte ho, to ek badi block banani padti hai aur saara purana data copy karna padta hai — ye step O(n) hai. Par yahan trick hai: agar tum capacity ko har baar double karte ho (×2), to resize bahut kam baar hota hai. Pure n appends ka total copy kaam 1+2+4+… < 2n hota hai, yaani O(n) total, to per-append average O(1) amortized. Agar galti se tum sirf +1 karke badhao, to har baar resize hoga aur total kaam n²/2 ho jaayega — bahut slow. Isliye yaad rakho: hamesha multiply karo, kabhi sirf add mat karo.

Ek aur chhupa hua faayda: cache locality. CPU ek baar me 64-byte ka "cache line" uthata hai. Array contiguous hai, to jab tum a[5] padhte ho, a[6], a[7]… already cache me aa jaate hain — almost free. Linked list me nodes memory me bikhre hote hain, har next ek cache-miss — isliye same O(n) hone par bhi array practically 5–10x fast nikalta hai. Yahi reason hai ki real competitive programming aur system code me array/vector pehli pasand hota hai.

Go deeper — visual, from zero

Test yourself — Linear Data Structures

Connections