Answers · Making it fast enough
Why does a hash table need to grow before it is completely full?
In shortBecause what makes lookup fast is how full the table is, not how big it is: near full, a lookup turns into a scan well before the last slot is taken.
A hash table is grown early because the quantity that sets lookup cost is the ratio of items to positions, not the number of positions. Left to fill, lookups stop being lookups and become scans: a table at ninety per cent full examines about twenty times as many slots per lookup as the same table at half full, and it still has a tenth of its positions free.
The cost is the fullness, not the room
Write for the fullness, the number of items divided by the number of positions. In an open-addressed table, where a collision means stepping along to the next free position, the number of slots examined by a search that finds nothing averages . Plug in values. At the term is , its square is , and , so the average is slots. At the same arithmetic gives , squared , reciprocal , and slots. At it gives , reciprocal , and . At : , reciprocal , average . At : , reciprocal , average . Nothing in that expression is the number of positions.
| fullness x | probing | chaining |
|---|---|---|
| 0.50 | 2.5 | 1.5 |
| 0.67 | 5.0 | 1.7 |
| 0.75 | 8.5 | 1.8 |
| 0.90 | 50.5 | 1.9 |
| 0.99 | 5000.5 | 2.0 |
A table of a thousand positions and a table of a thousand million positions at two thirds full both examine about five slots per unsuccessful search. A thousand million positions at ninety per cent full examines fifty. The size is irrelevant to the cost; the ratio is the whole of it. That is what it means for lookup to take the same time on ten items as on ten million, and it is why the fix for a slow table is to lower the ratio rather than to add room.
The natural reading of a rebuild is that the table ran out of space. It did not. At ninety-five per cent full there are still positions free and every insertion succeeds; the failure is time, not capacity. A search for a key that is not there walks about 200 slots at that fullness, and about 5000 at ninety-nine per cent. Adding positions helps only because it drops the ratio back to a third or so, not because the table could not hold one more key.
Why doubling, and what a rebuild costs
Start at 8 positions with a threshold of two thirds. The sixth insertion takes fullness from to , past the threshold, so a table of 16 positions is allocated and all 6 keys are put into it: 6 moves. The eleventh insertion gives , past it again, so 32 positions and 11 moves. The twenty-second gives , so 64 positions and 22 moves. Across the whole history, 22 insertions caused moves, which is moves per item.
The sum stays small because of the doubling: reading backwards from a final size of , each earlier rebuild moved half as many items as the one after it, and that series adds to less than twice the last term. So the rebuilding work, spread over all the insertions, is under two moves each, and the cost per insertion keeps its fixed bound. Growing by a fixed hundred positions instead gives a different series. With the same two thirds threshold, the table rebuilds at sizes 100, 200, 300 and up, and the rebuild at size moves items. Reaching 100,000 keys means rebuilds, so the total is moves, which is 334 moves per inserted key. The same table stopping at 1000 keys moves items, or 3.7 per key, so the per-item cost is growing with the table rather than standing still.
Where the argument stops
All of this counts on the hash spreading keys evenly. If it does not, fullness is a fiction: a table that is thirty per cent full with every key in one cluster behaves like a linked list of length whatever the ratio says, and no threshold saves it. The average is also not the worst case. The single insertion that crosses the threshold pays for moving every item present, and at ten million keys that pause is visible in a latency measurement even though the average insertion is cheap; systems with deadlines rehash a little at a time instead of all at once. And the threshold can be set too low as easily as too high: at one third full the probing formula gives slots against 5 at two thirds, a saving of about three slots for twice the memory.
Worth keeping
- Lookup cost depends on the number of items divided by the number of positions, and does not depend on the number of positions at all.
- Doubling at a fixed fullness threshold keeps the total moving work below two moves per item, which a fixed-size increment does not.
- The average insertion stays cheap but the one that triggers a rebuild is slow, so the average and the worst case are different claims.
Where this goes next
This question is one step of Finding It Instantly, a course that works through its subject from the beginning. The page that teaches this part of it is How Full Is Too Full, and it reads the whole way through whether or not you have an account.
What an account changes is the practice: problems standing under every idea, marked with a reason rather than a tick, in a copy of the course that is yours.
Read that pageThe whole courseOther questions people ask about this
- How does a hash function turn a word into an array index?A hash function reads the word as bytes, mixes them into one large number, then takes the remainder after dividing by the table size to get an index from zero to size minus one.
- How can you check whether something is in a set without storing every item?Record a few hashed marks per item in a bitmap; all marks set means probably present, any mark clear means certainly absent.
- Why can a hash table find something without scanning everything else?A hash table does not search its contents faster. It computes where the item must sit from the key itself, so the number of stored items never enters the calculation.
- Why can't a hash table give me the next key in order?Because a good hash deliberately scatters neighbouring keys, so the table keeps no record of which key comes after which; finding the next key means reading every entry.
- Why doesn't breadth-first search give the cheapest path once the links have different costs?Breadth-first search counts links rather than costs, so it can return a route with fewer links that is more expensive than a longer route.
- Why is O(2n) treated the same as O(n)?Because it describes how cost grows rather than exact cost, doubling every cost does not change the growth class.