Load Factor and Resizing
The Load Factor
The load factor measures how full a hash table is, where is the number of stored pairs and is the table size (number of slots).
As increases:
- For chaining: average chain length grows, so search and insert expected time grows as .
- For open addressing: the probability of finding an occupied slot increases sharply, and the expected number of probes grows as (unsuccessful search) or (successful search).
Why Resizing Is Necessary
A hash table with fixed capacity will eventually become overloaded if grows. Without resizing:
- Chaining: chain lengths grow linearly with , degrading to per operation.
- Open addressing: the table fills completely, and insertions fail (or probe sequences become impractically long before that).
Resizing is the operation of creating a new, larger table and rehashing all existing keys into it.
Resizing Strategy
When the load factor exceeds a threshold, double the table size (or increase to the next suitable prime):
- Allocate a new table of size .
- For each key in the old table, compute and insert into the new table.
- Replace the old table with the new one.
Thresholds: typically for chaining (some implementations use ) and for open addressing (the expected probe count at is only 2 for unsuccessful search).
Amortised Analysis of Resizing
A single resize costs because every key must be rehashed. If this happened on every insert, the insert cost would be , defeating the purpose.
However, resizing happens infrequently. If the table doubles each time:
- After inserts (from size to ), one resize costs .
- The inserts since the last resize each get charged an amortised for the resize cost, plus their own insert cost.
This is identical to the amortised analysis of dynamic arrays: the total cost of inserts starting from an empty table is , so the amortised cost per insert is .
Downsizing
If many deletions reduce significantly (e.g. ), the table can be downsized to reclaim memory. The same amortised argument applies: periodic downsizing adds amortised cost per deletion.
Avoid aggressive downsizing (e.g. at ), which could cause thrashing: a sequence of insert-delete-insert oscillating around the threshold, triggering repeated resizes.
Example: Resizing in Practice
Start with , threshold .
Insert 1: n=1, α=0.25, table=[1,_,_,_]
Insert 2: n=2, α=0.50, table=[1,2,_,_]
Insert 3: n=3, α=0.75, table=[1,2,3,_]
Insert 4: n=4, α=1.00 > 0.75 → RESIZE to m=8
Rehash all 4 existing keys into new table.
Total cost: Θ(4) for resize + Θ(1) for insert 4.
After resize, , well within the threshold.
Performance of Open Addressing with Resizing
With open addressing, tombstones also consume slots. When the fraction of tombstones becomes large, searches probe through many dead entries. A rehash into a same-size (or larger) table clears tombstones and restores performance. Maintain (live keys) and (tombstones); trigger rehash when exceeds threshold.
Summary
| Quantity | Meaning |
|---|---|
| Load factor | |
| Chaining threshold | Typically — |
| Open addressing threshold | Typically |
| Resize cost | (rehash all keys) |
| Amortised insert cost | (same analysis as dynamic arrays) |
| Resize trigger | exceeds threshold (or too many tombstones) |
| Downsizing | Reclaim memory when becomes very small |