Linear hashing visualizer
Linear hashing grows a hash table one bucket at a time with no directory: buckets are split in a fixed order by a split pointer, and keys that do not fit wait in overflow pages. Paste the keys from your exercise, choose the initial buckets, page size and split rule, and step through every placement and split.
Shaded index: already split this round, or created this round, so it uses mod 8. Pages after an arrow are overflow pages.
36 mod 4 = 0, which is below the split pointer, so use 36 mod 8 = 4: bucket 4.
- Keys
- 12
- Load factor
- 100.0%
- Overflow pages
- 0
- 112 mod 2 = 0: bucket 0.
- 227 mod 2 = 1: bucket 1.
- 35 mod 2 = 1: bucket 1.
- 440 mod 2 = 0: bucket 0.
- 533 mod 2 = 1: bucket 1, whose primary page is full, so the key goes to an overflow page.
- Bucket 1 overflowed, but linear hashing splits the bucket at the split pointer: bucket 0. Rehash its keys with mod 4: no keys move to new bucket 2.
- 618 mod 2 = 0, which is below the split pointer, so use 18 mod 4 = 2: bucket 2.
- 79 mod 2 = 1: bucket 1, whose primary page is full, so the key goes to an overflow page.
- Split bucket 1. Rehash its keys with mod 4: 27 moves to new bucket 3.
- The split pointer has passed every bucket of the round: level becomes 1 and the pointer returns to 0.
- 864 mod 4 = 0: bucket 0, whose primary page is full, so the key goes to an overflow page.
- Split bucket 0. Rehash its keys with mod 8: 12 moves to new bucket 4.
- 921 mod 4 = 1: bucket 1, whose primary page is full, so the key goes to an overflow page.
- Split bucket 1. Rehash its keys with mod 8: 5, 21 move to new bucket 5.
- 1050 mod 4 = 2: bucket 2.
- 117 mod 4 = 3: bucket 3.
- 1236 mod 4 = 0, which is below the split pointer, so use 36 mod 8 = 4: bucket 4.
| # | Operation | What happened | Level | Next | Buckets after |
|---|---|---|---|---|---|
| 1 | insert 12 | bucket 0 | 0 | 0 | 0: 12 1: – |
| 2 | insert 27 | bucket 1 | 0 | 0 | 0: 12 1: 27 |
| 3 | insert 5 | bucket 1 | 0 | 0 | 0: 12 1: 27 5 |
| 4 | insert 40 | bucket 0 | 0 | 0 | 0: 12 40 1: 27 5 |
| 5 | insert 33 | bucket 1 (overflow page), split 0 → 2 | 0 | 1 | 0: 12 40 1: 27 5 › 33 2: – |
| 6 | insert 18 | bucket 2 | 0 | 1 | 0: 12 40 1: 27 5 › 33 2: 18 |
| 7 | insert 9 | bucket 1 (overflow page), split 1 → 3, new round | 1 | 0 | 0: 12 40 1: 5 33 › 9 2: 18 3: 27 |
| 8 | insert 64 | bucket 0 (overflow page), split 0 → 4 | 1 | 1 | 0: 40 64 1: 5 33 › 9 2: 18 3: 27 4: 12 |
| 9 | insert 21 | bucket 1 (overflow page), split 1 → 5 | 1 | 2 | 0: 40 64 1: 33 9 2: 18 3: 27 4: 12 5: 5 21 |
| 10 | insert 50 | bucket 2 | 1 | 2 | 0: 40 64 1: 33 9 2: 18 50 3: 27 4: 12 5: 5 21 |
| 11 | insert 7 | bucket 3 | 1 | 2 | 0: 40 64 1: 33 9 2: 18 50 3: 27 7 4: 12 5: 5 21 |
| 12 | insert 36 | bucket 4 | 1 | 2 | 0: 40 64 1: 33 9 2: 18 50 3: 27 7 4: 12 36 5: 5 21 |
How to use the simulator
Type or paste the keys from your exercise and set the number of initial buckets N, how many keys fit on a page, and when to split. "Run all" inserts every key; "Start step by step" goes one key at a time. Each row of the drawing is a bucket: its primary page, then any overflow pages, with the split pointer marked. The answer table lists every step and the buckets after it, and "Copy answer" puts it on the clipboard as text.
- The hash function is the key modulo the current table size, as in textbook exercises.
- "A page overflows" is the classic rule: an insert that needs an overflow page triggers one split. The load-factor rules split whenever the table gets fuller than the threshold.
What is linear hashing?
Linear hashing is a hash index that grows smoothly as keys are added, one bucket per split, without ever rehashing the whole table and without the directory that extendible hashing needs. Its state is just the number of initial buckets N, the level L, which counts how many times the table has doubled, and the split pointer, which says which bucket will be split next.
The trick is that it does not split the bucket that overflows. It splits buckets in order, 0, 1, 2 and so on, and lets an overflowing bucket keep its extra keys in overflow pages until its turn comes. Since every bucket is split once per round, every overflow chain is eventually broken up.
Finding a key's bucket
Linear hashing uses a family of hash functions, each doubling the range of the last: hL(k) = k mod (N·2L). To find a key's bucket, compute hL(k). If the result is below the split pointer, that bucket has already been split this round and its keys were redistributed with the next function, so use hL+1(k) instead. Buckets from the split pointer onward, up to N·2L − 1, have not been split yet; buckets beyond that are the new halves created this round.
Splitting in order
A split takes the bucket at the split pointer, s, creates bucket s + N·2L at the end of the table, and rehashes the keys of s, including its overflow pages, with hL+1: each stays in s or moves to the new bucket. The split pointer then advances. When it reaches N·2L, every original bucket of the round has been split and the table has doubled, so L increases and the pointer returns to 0.
The default keys, 12, 27, 5, 40, 33, 18, 9, 64, 21, 50, 7, 36, with two initial buckets, two keys per page and splitting on overflow, cause 4 splits and end at level 1 with the split pointer at 2 and 6 buckets:
| Key | Buckets after | Level | Next | What happened |
|---|---|---|---|---|
| 12 | 2 | 0 | 0 | 12 mod 2 = 0: bucket 0. |
| 27 | 2 | 0 | 0 | 27 mod 2 = 1: bucket 1. |
| 5 | 2 | 0 | 0 | 5 mod 2 = 1: bucket 1. |
| 40 | 2 | 0 | 0 | 40 mod 2 = 0: bucket 0. |
| 33 | 3 | 0 | 1 | 33 mod 2 = 1: bucket 1, whose primary page is full, so the key goes to an overflow page. Bucket 1 overflowed, but linear hashing splits the bucket at the split pointer: bucket 0. Rehash its keys with mod 4: no keys move to new bucket 2. |
| 18 | 3 | 0 | 1 | 18 mod 2 = 0, which is below the split pointer, so use 18 mod 4 = 2: bucket 2. |
| 9 | 4 | 1 | 0 | 9 mod 2 = 1: bucket 1, whose primary page is full, so the key goes to an overflow page. Split bucket 1. Rehash its keys with mod 4: 27 moves to new bucket 3. The split pointer has passed every bucket of the round: level becomes 1 and the pointer returns to 0. |
| 64 | 5 | 1 | 1 | 64 mod 4 = 0: bucket 0, whose primary page is full, so the key goes to an overflow page. Split bucket 0. Rehash its keys with mod 8: 12 moves to new bucket 4. |
| 21 | 6 | 1 | 2 | 21 mod 4 = 1: bucket 1, whose primary page is full, so the key goes to an overflow page. Split bucket 1. Rehash its keys with mod 8: 5, 21 move to new bucket 5. |
| 50 | 6 | 1 | 2 | 50 mod 4 = 2: bucket 2. |
| 7 | 6 | 1 | 2 | 7 mod 4 = 3: bucket 3. |
| 36 | 6 | 1 | 2 | 36 mod 4 = 0, which is below the split pointer, so use 36 mod 8 = 4: bucket 4. |
When to split
Litwin's original rule splits once each time an insert overflows a page, which is also the rule in Ramakrishnan and Gehrke's textbook; with it the space use is not controlled directly. The alternative splits whenever the load factor, keys divided by primary slots, rises above a threshold, which lets the designer trade space for lookup cost. Inserting 20,000 random keys into a table with four initial buckets and four keys per page, averaged over five runs:
| Rule | Buckets | Load factor | Overflow pages | Pages read per lookup |
|---|---|---|---|---|
| Split on overflow | 7,190 | 69.5% | 1,235 | 1.123 |
| Split above 70% load | 7,143 | 70.0% | 1,251 | 1.125 |
| Split above 80% load | 6,250 | 80.0% | 1,602 | 1.175 |
| Split above 90% load | 5,556 | 90.0% | 1,886 | 1.215 |
Splitting on overflow settles near 70% full with random keys, close to what extendible hashing reaches. Pushing the threshold to 90% saves about a fifth of the buckets but makes the average lookup read more overflow pages.
Linear and extendible hashing
Both grow one bucket at a time. Extendible hashing splits exactly the bucket that overflows and keeps a directory to find it, so a lookup is one directory access and one bucket, but the directory can double suddenly and grows badly with skewed keys. Linear hashing has no directory to store or double, and its growth is perfectly regular, but buckets that overflow before their turn need overflow pages, and skewed keys can make those chains long. Under random keys the two fill their buckets about equally: 69.2% for extendible hashing in the same experiment.
History
Witold Litwin presented linear hashing in "Linear Hashing: A New Tool for File and Table Addressing" at the Very Large Data Bases conference in 1980, a year after extendible hashing was published. Its regular, directory-free growth made it popular for hash files and for in-memory tables that must grow without long pauses; Berkeley DB's hash access method is based on it.
Linear hashing questions and answers
How does linear hashing find a key’s bucket?
With N initial buckets and level L, compute h_L(k) = k mod (N·2^L). If the result is smaller than the split pointer, that bucket has already been split this round, so use h_(L+1)(k) = k mod (N·2^(L+1)) instead. No directory is needed: the level and the split pointer are enough.
Which bucket is split in linear hashing?
Always the bucket the split pointer points to, not the bucket that overflowed. Buckets are split in order 0, 1, 2, …; the overflowing bucket gets an overflow page and waits for its turn. This is what lets linear hashing avoid a directory, at the cost of temporary overflow chains.
When does the level increase?
When the split pointer reaches N·2^L, every bucket that existed at the start of the round has been split, so the table has doubled. The level increases by one and the split pointer goes back to 0.
What is the difference between linear hashing and extendible hashing?
Extendible hashing keeps a directory and splits exactly the bucket that overflows, so a lookup reads one directory entry and one bucket. Linear hashing has no directory and splits buckets in a fixed order, so a lookup may read overflow pages. In this page’s model, with 20,000 random keys and four keys per page, splitting on overflow left buckets 69.5% full on average and a lookup read 1.12 pages; extendible hashing fills its buckets about as well (69.2%) with exactly one bucket read but a directory to maintain.
What is the load factor in linear hashing?
The number of keys divided by the number of slots in primary pages. A load-factor trigger splits a bucket whenever it rises above a threshold, which keeps the table as full as you choose: at 90% the model kept buckets 90.0% full but needed 1.22 pages per lookup, against 1.12 at 70%.
Where is linear hashing used?
Witold Litwin introduced it in 1980 for files and tables that grow, and it has been used in database hash indexes and in-memory hash tables that must grow without pausing to rehash everything; Berkeley DB’s hash access method is based on it.
Further reading
- WikipediaLinear hashingThe algorithm, its variants and the reference to Litwin's 1980 paper.
- Ramakrishnan and GehrkeDatabase Management SystemsThe chapter on hash-based indexing covers linear and extendible hashing side by side.
- Oracle Berkeley DB documentationAccess Method ConfigurationBerkeley DB's Hash access method, an implementation of Litwin's linear hashing.