edubun 한국어

Hash tables

With 47 stored in a table of 7 buckets, the computer goes straight to bucket 47 mod 7 = 5 instead of searching the whole table.

Turning a key into a position

So far, finding a value meant searching: up to n steps in an unsorted array or a linked list. Arrays, though, can reach any position in one step. What if the key itself told you the position? If your keys were small whole numbers, say student numbers from 0 to 99, you could keep an array of 100 cells and store student k in cell k. MIT's notes call this a direct access array. It fails when the possible keys are huge, like phone numbers or words, because you cannot afford a cell for every possible key.

A hash function solves that by squeezing any key into a small range of positions, 0 to m − 1. A simple one for whole numbers is h(k) = k mod m, the remainder after dividing by m. The array of m cells is the hash table, and its cells are often called buckets. To store 47 with m = 7, compute 47 mod 7 = 5 and put it in bucket 5. To find 47 later, compute the same thing and look only in bucket 5.

Collisions and chaining

There is a problem. With 7 buckets and more than 7 possible keys, some keys must share a bucket: 12, 33 and 47 all give remainder 5. This is called a collision, and MIT's notes point out that it cannot be avoided, by the pigeonhole principle. The usual remedy is chaining: each bucket holds a small list, a chain, of every key that hashed there. Finding 47 then costs 1 step for the hash plus one comparison for each key checked in chain 5. If 12 and 33 are ahead of it, that is 1 + 3 = 4 steps.

How long are the chains? If the keys spread evenly, each chain holds about n/m keys, a number called the load factor. Keep m about as large as n and the chains stay short, so finding, inserting and deleting take a constant number of steps on average. The danger is a bad spread. If every key hashes to the same bucket, one chain holds all n keys and the table is no better than a linked list. In the lab, set 7 buckets and insert 14, 21 and 28: they all land in bucket 0.

Loading

Drag to turn. Scroll or pinch to zoom.

A hash table of 7 buckets holding 12, 25, 33, 47 and 70, with h(k) = k mod 7. Choose a key and insert, find or delete. The step counter is 1 for the hash plus 1 for every key compared in the chain.
Real hash functions mix all the bits of a key, and well-designed libraries choose them so that ordinary data spreads evenly. MIT's 6.006 goes further and picks a hash function at random from a family, so that no fixed set of keys is bad every time. The plain k mod m in the lab is chosen because you can check it by hand.

Hash tables in JavaScript

You seldom write a hash table yourself, because JavaScript has Map and Set. The ECMAScript specification says they "must be implemented using either hash tables or other mechanisms that, on average, provide access times that are sublinear on the number of elements". In other words, map.get(key) and set.has(x) must be faster than searching the whole collection. MDN adds that a Map keeps keys in insertion order and, unlike a plain object, contains no default keys that could collide with yours.

const price = new Map();
price.set("apple", 1.2);
price.set("bread", 2.5);
console.log(price.get("bread")); // 2.5, no search through the list
console.log(price.has("milk"));  // false
const seen = new Set([4, 8, 15]);
console.log(seen.has(8));        // true
BackgroundThe idea of hashing is credited to Hans Peter Luhn of IBM. Donald Knuth's history of searching records that in January 1953 Luhn wrote an internal IBM memorandum suggesting that records be put into numbered buckets, with chaining for the ones that collide. His hash functions worked on digits: add neighbouring pairs of digits and keep the last digit of each sum, so 31415926 becomes 4548. Other IBM engineers working on the IBM 701 had the same idea at about the same time, and the first published description came from Arnold Dumey in 1956.
Hash functionTurns a key into a bucket number from 0 to m − 1, for example k mod m.
CollisionTwo different keys get the same bucket. Unavoidable when keys outnumber buckets.
ChainingEach bucket keeps a list of every key that hashed there.
Load factorn/m, the average chain length.
Map and SetJavaScript's built-in keyed collections, required to be faster than linear on average.
  1. With h(k) = k mod 7, which bucket does 47 go into?
  2. The table holds 12, 25, 33, 47, 70 (inserted in that order) with m = 7. How many steps does finding 47 take (1 for the hash plus keys compared)?
  3. Same table: how many steps for finding 12?
  4. Same table: 19 is not stored. How many steps does a search for 19 take?
  5. Same table: what is the load factor n/m? (two decimal places)
  6. What is a collision?
    • A key that is too large
    • Two different keys hashing to the same bucket
    • Deleting a key twice
    • A table with no keys
  7. Why can no hash function avoid collisions when there are more possible keys than buckets?
    • Computers round numbers
    • The pigeonhole principle
    • Keys are always even
    • Chains are too short
  8. If every key lands in the same bucket, how does finding a key behave?
    • Still 1 step
    • Like searching a linked list of n keys
    • It becomes impossible
    • Like binary search
  9. What does the ECMAScript specification require of Map access times?
    • Exactly 1 step
    • Sublinear in the number of elements, on average
    • Θ(n log n)
    • Nothing
  10. Luhn's 1953 hash added neighbouring digit pairs and kept the last digit of each sum. What does 31415926 become?
Key points
  • A hash function turns a key into a bucket number; k mod m is a simple one.
  • Collisions are unavoidable; chaining keeps a list in each bucket.
  • With load factor n/m kept small, find, insert and delete take constant steps on average.
  • JavaScript Map and Set must be faster than linear on average.
Sources for this course (5)
  • MIT OpenCourseWare 6.006 Introduction to Algorithms, Spring 2020 (Demaine, Ku, Solomon), lecture notes 2 Data Structures (interface vs data structure, Sequence and Set interfaces, stack = insert_last/delete_last, queue = insert_last/delete_first, array, linked list, dynamic array, amortized Θ(1) append), 4 Hashing (chaining, pigeonhole collisions, chain length n/m), 6 Binary Trees Part 1 (height, traversal order, O(h) operations) and 7 Binary Trees Part 2: AVL (Adelson-Velsky and Landis, 1962) at ocw.mit.edu/courses/6-006-introduction-to-algorithms-spring-2020/pages/lecture-notes
  • MDN Web Docs, Array.prototype.shift (shifts all values left by 1), Array.prototype.unshift, Map (insertion order, Map vs Object, spec requires sublinear average access) and Set (developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects)
  • ECMAScript 2025 Language Specification (tc39.es/ecma262), 24.1 Map Objects and 24.2 Set Objects ("must be implemented using either hash tables or other mechanisms that, on average, provide access times that are sublinear on the number of elements"), Array.prototype.shift steps (Repeat, while k < len: move element k to k - 1)
  • D. E. Knuth, The Art of Computer Programming vol. 3 (2nd ed. 1998) section 6.4 History (H. P. Luhn, IBM internal memorandum January 1953, hashing with chaining; digit pairs added mod 10, 31415926 -> 4548) via gwern.net copy, and IEEE Spectrum, "Hans Peter Luhn and the Birth of the Hashing Algorithm" (2018)
  • "A brief history of the stack", SIGCIS (sigcis.org/files/A brief history.pdf: Bauer and Samelson applied for the patent in 1957, US 3,047,228 granted July 31, 1962; IPL list processing by Newell, Simon and Shaw at RAND 1956) and Wikipedia, Information Processing Language (Newell, Shaw, Simon, RAND and Carnegie Institute of Technology, about 1956).

Checked: 2026-10-18