Computer Science / Hash Tables & Collision Resolution
FREE TO EXPLORE
LABORATORY 09 · COMPUTER SCIENCE

Hash Tables & Collision Resolution lab report

A worked hash tables & collision resolution lab report with benchmark data tables, asymptotic graphs, calculations, uncertainty and conclusions.

WORKED EXAMPLE · BENCHMARK OBSERVATIONS

A complete example laboratory report.

Simulated demonstration data.

This report illustrates formal algorithmic benchmarking, operation counting arithmetic, and regression analysis. Replace its observations with your own benchmark telemetry when preparing a practical submission.

Student: __________________Student ID: __________________Course: __________________Date: __________________Partner: __________________Instructor: __________________

1. Title and aim

Empirical Analysis of Hash Tables and Collision Resolution: Separate Chaining vs. Open Addressing (Linear Probing, Quadratic Probing, Double Hashing), Load Factor α = n / m, Primary/Secondary Clustering, and Asymptotic Probe Lengths. To investigate hash table collision resolution mechanics, measure empirical probe depth distributions across Separate Chaining, Linear Probing, Quadratic Probing, and Double Hashing, quantify the primary clustering phenomenon, and verify Knuth's asymptotic probe theorem E[P] = 1 / (1 − α) across load factors α ∈ [0.10, 0.90] in a 1000-slot table.

2. Abstract

Seven benchmark trials were generated across key dataset sizes n = 100 to n = 900 keys in a fixed 1000-slot hash table (load factors α from 0.10 to 0.90, transformed load coordinate x = 1 / (1 − α) from 1.1111 to 10.0000, expected unsuccessful search probe lengths E[P] from 1.1111 to 10.0000 probes). An ordinary least-squares regression of probe depths against the transformed load coordinate yielded an empirical probe scaling coefficient of 1.0000 probes/interval, demonstrating exact agreement with Knuth's uniform hashing theorem (difference = 0.0001%). The empirical telemetry confirms that Double Hashing completely eliminates primary and secondary clustering, achieving the optimal theoretical probe bound E[P] = 1 / (1 − α) and outperforming Linear Probing by a factor of 5× at high load factors (α = 0.90).

3. Apparatus and fixed settings

4. Theory and graph choice

A Hash Table is a foundational associative data structure that implements an abstract dictionary mapping keys to values with average-case O(1) time complexity. Because the universe of possible keys U is infinitely larger than the table capacity m (|U| >> m), the Pigeonhole Principle dictates that hash collisions—where distinct keys k_1 ≠ k_2 produce identical hash indices h(k_1) = h(k_2)—are mathematically inevitable. Collision resolution strategies diverge into two fundamental architectural paradigms: (1) Closed Addressing (Separate Chaining), which maintains dynamic external linked lists for each bucket, tolerating load factors α = n/m > 1 at the expense of pointer dereferencing overhead and non-contiguous CPU cache line misses; and (2) Open Addressing, which stores all elements directly within the contiguous table array (enforcing α < 1) by calculating a systematic probe sequence h(k, i) across unoccupied slots. Under Open Addressing, naive Linear Probing h(k, i) = (h(k) + i) mod m suffers from destructive Primary Clustering, where contiguous runs of occupied slots merge into expanding clusters that act as gravitational attractors, causing probe lengths to explode quadratically according to Knuth's bound E[P] ≈ 0.5(1 + 1/(1-α)²). Quadratic Probing h(k, i) = (h(k) + c₁i + c₂i²) mod m mitigates primary clustering but exhibits secondary clustering. Double Hashing h(k, i) = (h₁(k) + i·h₂(k)) mod m utilizes an independent secondary hash stride h₂(k) coprime to m to produce pseudo-random cyclic permutations, completely eliminating clustering and achieving the theoretical uniform hashing probe bound E[P_unsuccessful] = 1 / (1 − α). Linearizing empirical probe depths against the coordinate x = 1 / (1 − α) provides a mathematically rigorous foundation for verifying hash table scaling and optimizing cache-conscious hash maps.

E[P_unsuccessful](α) = k_hash · [1 / (1 − α)] + P_0 = 1.0000 · [1 / (1 − α)] + 0.0000 probes

The mathematical regression fits the linear model y = mx + b, where x = 1 / (1 − α) represents the transformed load factor coordinate, y = E[P] represents the expected number of memory probes in an unsuccessful search, m represents the probe scaling factor k_hash, and b represents the baseline probe offset (theoretically b = 0.0000 probes). The gradient has physical units probes/interval.

5. Method

  1. Initialize a contiguous hash table buffer of m = 1000 slots. Clear all slots to the empty sentinel indicator (NULL). Set the double hashing secondary prime parameter to 997 to guarantee coprimality gcd(h₂(k), m) = 1 across all integer keys.
  2. Generate a pseudorandom stream of distinct 64-bit integer keys. Pass keys through the MurmurHash3 engine and verify that base hash values h(k) mod m exhibit a uniform distribution across all 1000 buckets without systematic clustering.
  3. Insert keys sequentially from index 0 to n − 1. When an occupied slot is encountered, invoke the Double Hashing protocol h(k, i) = (h₁(k) + i·h₂(k)) mod m. Increment the probe counter for each slot inspected until an empty slot is reached and the key is committed.
  4. Record the complete hash table state at each sample scale n ∈ [100, 250, 400, 500, 650, 800, 900] keys, corresponding to load factors α = n / m ∈ [0.10, 0.25, 0.40, 0.50, 0.65, 0.80, 0.90].
  5. Execute 10,000 synthetic unsuccessful search queries using keys guaranteed not to reside in the table. For each query, trace the probe sequence h(k, 0), h(k, 1), h(k, 2), ... until the first NULL slot is detected. Compute the empirical mean probe depth E[P].
  6. Transform load factors α into the linearized coordinate x = 1 / (1 − α). Regress empirical probe counts E[P] against x. Calculate the regression slope k_hash, intercept b, coefficient of determination R², and standard errors to validate Knuth's theorem.

6. Observations and calculation table

All benchmark observations use strictly controlled memory buffers. Values are recorded deterministically from the algorithmic comparator register. Residuals are computed relative to the ordinary least-squares regression line.

Table 1. Seven simulated algorithmic benchmarks; x and y represent computational state metrics.
No.Key dataset size n (keys stored in m = 1000 slot table) (keys)Expected unsuccessful search probe length E[P] (probes)Transformed load coordinate 1 / (1 − α) (dimensionless)Expected probe length E[P] (memory accesses)Fitted yResidual
11001.11111.11111.11111.1111-0.0000
22501.33331.33331.33331.3333-0.0000
34001.66671.66671.66671.66670.0000
45002.02.00002.00002.00000.0000
56502.85712.85712.85712.8571-0.0000
68005.05.00005.00005.00000.0000
790010.010.000010.000010.00000.0000

Download the sample observations (CSV) ↓

7. Worked calculation for one observation

Table Capacity m = 1000 slots; Key Dataset Size n = 100 keys; Load Factor α = 100 / 1000 = 0.1000. Transformed Load Coordinate: x = 1 / (1 − α) = 1 / (1 − 0.1000) = 1.1111. Expected Unsuccessful Search Probe Depth: E[P] = 1 / (1 − α) = 1.1111 memory probes. Verification: Under uniform hashing, the probability of requiring at least i probes is α^(i-1); summing the geometric tail series ∑_{j=0}^∞ α^j yields strictly 1 / (1 − α) = 1.1111 probes.

8. Graph, gradient and final calculation

-0.220.042.672.805.565.568.448.3111.3311.07Transformed load coordinate 1 / (1 − α) (dimensionless)Expected probe length E[P] (memory accesses)n = 100n = 250n = 400n = 500n = 650n = 800n = 900

Circular markers represent empirical benchmark observations. The solid line represents the ordinary least-squares asymptotic linear fit.

x̄ = 3.42404; ȳ = 3.42403
Σ(x − x̄)² = 60.88522
Σ(x − x̄)(y − ȳ) = 60.88528
m = Σ(x − x̄)(y − ȳ) / Σ(x − x̄)² = 1.00000100
b = ȳ − mx̄ = -1.1146e-05
k_hash = m = 1.0000 probes/interval; Intercept P_0 = -1.1146e-05 probes (theoretical k_hash = 1.0000, P_0 = 0.0000)

9. Uncertainty and comparison

Percentage difference = |estimate − theoretical value| / |theoretical value| × 100 = 0.0001%.

For n = 7 benchmark observations, Σresidual² = 3.7050e-09; s² = Σresidual²/(n − 2). Gradient standard error = √[s²/Σ(x − x̄)²] = 3.4886e-06. Intercept standard error = √[s²(1/n + x̄²/Σ(x − x̄)²)] = 1.5765e-05.

Propagating the fit parameters yields a fit standard error of 3.4886e-06 probes/interval, with an ideal coefficient of determination R² = 1.000000.

In discrete hash table analysis, the expected unsuccessful search probe depth E[P] = 1 / (1 − α) under the Uniform Hashing Assumption is an exact mathematical expectation. Unlike continuous physical instrumentation, there is no analog sensor noise, thermal drift, or calibration variance in counting discrete memory bucket probes. However, in physical semiconductor microprocessors, wall-clock hash lookup latency is strongly modulated by memory hierarchy and pipeline dynamics: (1) L1/L2 data cache hit ratios and Translation Lookaside Buffer (TLB) page table walks, where contiguous array buffers (Linear Probing) execute within ~1–4 CPU cycles while non-contiguous pointer dereferencing (Separate Chaining) incurs ~100–250 CPU cycles; (2) Primary clustering in linear probing, which forces probe paths into contiguous occupied runs and causes quadratic latency degradation E[P] ≈ 0.5(1 + 1/(1-α)²); (3) Branch predictor mispredictions during probe loop termination checks (`if (table[slot] == NULL)`), which stall superscalar execution pipelines by 15–20 clock cycles; and (4) Hash function computational overhead, where high-entropy 64-bit avalanche functions (MurmurHash3, SipHash) eliminate bucket resonance at the cost of 5–15 CPU instructions per hash. Ordinary least-squares linear regression of observed probe lengths against transformed load coordinates x = 1 / (1 − α) yields an empirical scaling slope k_hash = 1.0000 probes/interval with zero residual variance (R² = 1.00000), verifying Knuth's uniform hashing theorem with mathematical certitude.

10. Result and discussion

k_hash = 1.0000 probes/interval
Theoretical reference value: 1.0000 probes/interval

The empirical benchmark observations provide rigorous quantitative verification of Knuth's asymptotic probe bounds in open-address hash tables. As key count n increases from 100 to 900 keys (load factor α from 0.10 to 0.90), the raw probe length exhibits a dramatic non-linear acceleration, rising from 1.1111 probes at α = 0.10 to 10.0000 probes at α = 0.90. Plotting probe depths against the linearized coordinate x = 1 / (1 − α) transforms this asymptotic divergence into a straight line with slope m = 1.0000 and R² = 1.00000, confirming that the number of unsuccessful search probes follows a geometric distribution with success parameter p = 1 − α. Comparative analysis across collision resolution strategies reveals profound architectural trade-offs: Separate Chaining tolerates load factors α > 1.0 and degrades linearly (E[P] = α), but incurs severe CPU cache misses due to pointer chasing across fragmented heap memory. Linear Probing maximizes CPU L1 spatial cache locality by scanning adjacent array slots, but suffers from catastrophic Primary Clustering where contiguous runs act as gravitational attractors, squaring the probe penalty to E[P] ≈ 0.5(1 + 1/(1-α)²). Double Hashing eliminates both primary and secondary clustering by varying the probe stride as a function of the key itself (h₂(k) coprime to m), achieving the ideal theoretical probe bound 1 / (1 − α). Finally, the investigation demonstrates why modern systems libraries (such as Google Abseil Swiss Tables and Rust hashbrown) pair open addressing with 1-byte control arrays and SIMD vector instructions to inspect 16 slots simultaneously in L1 cache.

11. Precautions and limitations

The simulated execution environment models idealized open addressing under uniform pseudo-random hashing where key probes follow independent permutations without hash function bias. In physical microprocessors, actual hash lookup throughput is governed by CPU L1/L2 data cache hit rates, translation lookaside buffer (TLB) misses during table accesses exceeding 2 MB pages, branch mispredictions during probe loop termination checks, and memory bus latency during DRAM cache line fetches. Knuth's uniform hashing theorem establishes that in an open-address hash table with load factor α = n/m, the number of probes required in an unsuccessful search follows a geometric distribution with success parameter p = 1 − α, yielding expected probe depth E[P_unsuccessful] = 1 / (1 − α) and successful search depth E[P_successful] ≈ (1/α) ln(1 / (1 − α)). Linearizing this relationship transforms the asymptotic divergence at α → 1 into a linear slope k_hash = 1.0000 probes/interval.

12. Conclusion

This laboratory investigation quantitatively verified the collision resolution mechanics, probe distributions, and asymptotic load scaling of Hash Tables. Through systematic benchmarking across load factors from α = 0.10 to α = 0.90, we verified the empirical probe scaling factor k_hash = 1.0000 probes/interval with an ideal R² = 1.00000. The investigation established the microarchitectural trade-offs between cache-friendly contiguous arrays and pointer-based chaining, proving why Double Hashing, Robin Hood equalized probing, and SIMD control-byte Swiss Tables form the core dictionary implementation of modern operating systems, database indexes, and high-throughput compilers.