Linear probing 2026-10-18
An open addressing probe rule that visits modulo , using modular arithmetic, until a matching record or an appropriate stopping slot is found.[ref]
For capacity , the hash table probe numbered , starting at zero, inspects the array index
The hash function gives the first array index. Each subsequent hash table probe moves one slot forward, wrapping from to by modular arithmetic. Keep the hash function and key equality fixed while hash table records are stored.
Use three distinguishable slot states: occupied by a live hash table record; never used since initialization or rebuilding, written E; or deleted, written D, a tombstone in open addressing. Lookup compares occupied hash table keys using key equality, stops at E, and continues past D.[ref]
For an original example, take an eight-slot array, integer hash table keys, and the hash function . Start with all slots E and insert the hash table records in that order. The insertion hash table probe traces, expressed as array indices, are
The resulting array holds hash table keys at array indices , with E in the other four slots. The first three hash table keys have the same initial array index, a hash collision; the fourth begins at but joins the same linear probing cluster. Lookup of examines array indices , rejecting before returning . Lookup of absent examines , including the stopping E: five hash table probes for a hash table load factor .
Figure 1.
Four insertions build a linear probing cluster, followed by lookup of hash table key
. Original deterministic eight-slot example, with hash table keys shown and associated values omitted. Orange numbers count hash table probes in order; green marks placement or a match. Each row follows the preceding row. Details.
Bound lookup to at most hash table probes, even if no E remains. For algorithm termination, the first array indices are distinct: equality of and implies that divides by modular arithmetic, and forces . They therefore cover the entire finite set of slots exactly once. If no occupied hash table key matches and no E is encountered, exhausting these hash table probes establishes absence; wrapping around again supplies no new information.[ref]
The attraction is a compact array and a simple hash table probe rule. Consecutive slots can benefit from spatial locality, although actual memory cache behavior depends on representation and hardware. Correctness rests on preserving the search route; speed depends on how long that route becomes. The linear probing cluster below explains why even a moderate hash table load factor gives no universal constant lookup bound.
Linear probing cluster 2026-10-18
A maximal consecutive run of occupied or deleted slots in linear probing, bounded by never-used slots when any exist; adjacency wraps around by modular arithmetic. Deleted slots still belong to the search run.[ref]
In the eight-slot example, array indices form one linear probing cluster. Inserting absent hash table key starts at , passes the occupied slots , and fills . This extends the same linear probing cluster despite having a different initial array index from . A hash collision at the initial slot is enough to make later slots compete too.
For a worst-case family, insert integer hash table keys into an empty capacity- array, using the hash function , where . They occupy array indices . Lookup of absent needs hash table probes. Taking gives hash table load factor at most while the number of hash table probes grows with . Thus occupancy alone cannot promise constant lookup work.
Before any rebuilding, bounded lookup, deletion by hash table key, and insertion with a duplicate check each have worst-case time complexity in Big O notation, assuming constant-cost hash function evaluation, array access and key equality. The counterexample gives a matching linear worst-case growth in the number of hash table probes. Hash table resizing is additional work; expensive string comparisons or hashing also fall outside these constant-cost assumptions.
Load factor of a hash table Created 2026-10-13 Updated 2026-10-18
The number of stored records divided by the number of hash buckets. For separate chaining, this is the mean chain length over all hash buckets, including empty ones.
Consider two original separate chaining placements using the deterministic hash function on nonnegative integer keys. With , keys give the balanced chain lengths . Instead, keys all select hash bucket , giving . Both store records, so both have . The maximum chain lengths are and . These are constructed placements, not measured workloads.
Figure 1.
The same hash table load factor permits balanced and concentrated hash bucket occupancies
. Both original examples use eight hash buckets and twelve distinct integer keys. Every outlined column counts towards , including empty ones; each colored square represents one record. The dashed line marks the arithmetic mean , not the maximum chain length. Details.
For an absent query, separate chaining inspects every record in the selected hash bucket. Key selects hash bucket in both examples but is stored in neither, so it takes two key equality comparisons in the balanced placement and twelve in the concentrated placement. Key selects hash bucket and instead takes one comparison in the balanced placement and zero in the concentrated placement. If an absent query's bucket index has the uniform distribution on a finite set of eight indices, its mean comparison count is in either fixed placement. That average does not limit the cost of a particular query.
For successful lookups, suppose each of the twelve stored keys is queried with equal probability, with fixed chain order and no rearrangement on access. A chain of length contributes comparison counts , irrespective of its order. Thus
The balanced placement gives comparisons; the concentrated placement gives . Even this average depends on more than : concentration appears through the squared chain lengths. These exact counts exclude computing the hash function, locating the hash bucket, and allocating records. Elapsed lookup time also depends on the cost of key equality, key length, and memory access latency; alone specifies none of them.
The expected time complexity bound for separate chaining needs a probabilistic assumption. Fix distinct stored keys and a query independently of the random choice of hash function, and require for every unequal pair, where is a constant independent of . With constant-cost hashing, array access and key equality, this suffices. The authored chaining analysis cited here uses this pairwise-collision argument; its multiplicative construction has , rather than the of simple uniform hashing.[ref]
For the proof outline, let be the indicator random variable that stored key shares an absent query 's hash bucket. By linearity of expectation,
A present query's full chain contains itself plus at most other records, giving . Stopping at the match can only improve this bound. Full independence is unnecessary for this calculation, but fixed known hash functions and keys chosen adaptively to collide are outside the stated assumption. Keeping bounded then controls expected lookup work, while the concentrated example still explains why it gives no worst-case guarantee.
For the balanced twelve-record map, put(3,new_value) replaces a value, so and remain unchanged. An absent key such as instead adds a thirteenth record, giving if capacity stays fixed. Under a policy that stores every repeated-key record separately, another record with key would also increase ; all equal-key records necessarily share a hash bucket when the hash function respects key equality. State the map policy before interpreting the count.
The appeal of the hash table load factor is that one number helps tune a space-versus-search tradeoff: more hash buckets require more array storage and can reduce expected search work under the stated assumptions. The actual chain lengths and query choices still matter.
In open addressing, counts record slots and counts live records, so . A policy retaining at least one genuinely empty slot requires ; being below one is not itself a speed guarantee. For deletion using a tombstone in open addressing, also track , the number of marked slots: counts slots that cannot terminate an unsuccessful probe. For example, gives live occupancy but nonempty-or-marked occupancy . These ratios answer different questions.[ref]
A deleted-slot marker in open addressing. Lookup continues past it because a hash collision may have displaced a match further along. Linear probing can reuse the slot for insertion after checking for an existing equal key. A genuinely empty slot can terminate lookup; this marker cannot.[ref]
Delete hash table key from the original eight-slot example. Writing E into array index makes lookup of inspect and incorrectly report absence, although its hash table record remains at . Writing D instead makes lookup pass and reach , returning after three hash table probes. The deleted slot must remember that the search route once continued through it.
Figure 1.
Deleting to an empty slot breaks lookup; a tombstone in open addressing preserves the search route
. Original deterministic comparison: the middle and lower rows are alternative deletions from the top row. E means never used and stops lookup; D means deleted and lets lookup continue. Orange numbers give the hash table probe order for hash table key . Details.
A short algorithm correctness proof uses this invariant: no never-used slot precedes a stored hash table key along its linear probing route. Initially the claim is vacuous. Insertion places a new hash table record no later than the first E, possibly at an earlier D, and cannot create an E before another stored hash table record. Replacing a value leaves all slots occupied as before. Deletion to D also creates no E. By mathematical induction over operations, the invariant persists, so stopping lookup at E is sound. Deletion directly to E invalidates that argument, as the diagram shows.
To implement the hash table map operation put(k,v) in one bounded scan, remember the first D encountered, but keep checking occupied hash table keys. A later key equality match means replace that hash table record's value and stop. Only after reaching E, or completing hash table probes, is absence established. Then insert at the remembered D, if any; otherwise use the stopping E. If all slots are occupied and no match exists, report full or rebuild before trying again. Merely finding D is not permission to create a second equal hash table key.[ref]
Continue from the correctly deleted example, with hash table keys at array indices and D at . put(16,Z) examines and updates the value at , leaving deleted and retaining three live hash table records. Inserting immediately at would instead create two copies of . Now put(24,W) examines , proves absence at E, and places the new hash table record at the remembered array index . The hash table load factor rises from to ; reusing D avoids extending the linear probing cluster to .
For a boundary case, fill all eight slots with hash table keys and then delete all eight to D. The live hash table load factor is zero, but absent lookup of still needs eight hash table probes. put(16,C) also checks eight slots before reusing the first D, at array index . A loop that waits indefinitely for E would never finish in this state. Rebuilding from the live hash table records into a fresh array removes each tombstone in open addressing and restores never-used stopping slots.[ref]