Dictionary ADT and Hashing: Understanding Table Lookup and Collision Resolution - Prof. Su, Study notes of Algorithms and Programming

An outline of a lecture on data structures and algorithms, focusing on the dictionary adt and hashing. Topics include table lookup, searching for items, types of dictionaries, runtime analysis, and implementing function call. The lecture also covers the concept of symbol tables and their implementation using hash tables and hashing functions. The importance of a good hash function, string hashing, compression mapping, and collision resolution methods such as separate chaining, scatter table, and open addressing.

Typology: Study notes

Pre 2010

Uploaded on 09/02/2009

koofers-user-u68
koofers-user-u68 🇺🇸

10 documents

1 / 20

Toggle sidebar

This page cannot be seen from the preview

Don't miss anything!

bg1
Outline
Last time:
Review of basic ADTs
PA1 Walk Through
Today:
Continue PA1 Walk Through
Dictionary ADT
Hashing
Sugih Jamin ([email protected])
pf3
pf4
pf5
pf8
pf9
pfa
pfd
pfe
pff
pf12
pf13
pf14

Partial preview of the text

Download Dictionary ADT and Hashing: Understanding Table Lookup and Collision Resolution - Prof. Su and more Study notes Algorithms and Programming in PDF only on Docsity!

Outline

Last time:

  • Review of basic ADTs
  • PA1 Walk Through

Today:

  • Continue PA1 Walk Through
  • Dictionary ADT
  • Hashing

Dictionary ADT

Table lookup: look up a key in a table

The key is associated with some other information ( value )

Key space is usually more structured/regular than value space, so easier to search

An entry is a <key, value> pair

For example: <title, mp3 file>

Usually the ADT stores pointers to entries

Runtime

Unsorted list:

  • insert: O()
  • search: O()

Sorted list:

  • insert: O()
  • search: O()

Dictionary ADT Application: Implementing Function Call

Consider:

10 foo() { /* does something / } 20 bar() { / does something else */ } 32 main() { foo(); bar(); }

How does main() know where foo() and bar() are?

Symbol Table

Symbol table:

  • constructed by the assembler
  • maps symbols to binary addresses
  • used by the linker to resolve symbol references (perhaps across different object files)
  • used by the debugger to find where the symbols are

% g++ -g a.cc

The -g option tells g++ to save the symbol table Otherwise it will be removed to save disk space

Implementing Symbol Table

Which ADT to use for symbol table?

How shall we implement this ADT? As array? As linked list?

Hash Table and Hashing

Reference items in a table (the hash table) by keys

Use arithmetic operations to transform keys into table addresses (buckets)

Hash function (h()): transforms the search key into a bucket

  • hash code : t(key) → intmap maps the key (which could be a string, etc.) into an integer (intmap)
  • compression map : c(intmap) → bucket maps the intmap into an address within the table, i.e., into the range [0, M − 1], for table of size M

Given a key: h(key) → c(t(key)) → bucket/index

Hashing Example and Complexity

Example 1 : hash table of size 5, want to insert 4, 3, 6, 22

How does insert (unordered) and search on a hash table work? What would be an example hash function?

What are their time complexities?

Example 2 : hash table of size 4, want to insert 4, 3, 6, 22 What to do with keys that hash into the same bucket?

Moral: Pick a table size (M ) that doesn’t have common factors with the key Prime numbers are good candidates

Hash Functions (cont)

Common parts of hashing function:

  • truncation (hash code): remove parts common across keys, or extract bits from keys that are more likely to be unique acros keys. Examples: o 734 763 1583 o 141.213.8. 193 o cello .eecs. umich .edu
  • folding (hash code)
  • modulo arithmetic (compression map)

What if the keys are not integers?

  • string: use the ASCII encoding of each char
  • float: treat it as a string of bits
  • in general, treat the representation as a bit-string and sum up or extract parts of it

String Hashing

Example symbol table:

Bucket Symbol Memory Location h(“foo”) = 0 “foo” 10 1 2 h(“bar”) = 3 “bar” 20 4 5 6 h(“main”) = 7 “main” 32 8

What is my hash function?

int hash(char s, int M) / s string to be hashed, M table size */

Consider these strings: “stop”, “tops”,“pots”,“spot” How would they hash into my table using the above hash function?

Compression Mapping

  • division method: |intmap| mod M, M table size (prime)
  • MAD (multiply and divide) method: |a ∗ intmap + b| mod M , a and b non-negative integers

Hashing: Collision Resolution

With hashing, collision is inevitable

What do you do when two items hash into the same bucket/bin?

Methods of collision resolution:

  • separate chaining
  • scatter table o coalesced chaining o open addressing: - linear probing - quadratic probing - double hashing
  • extensible hashing: dynamic hashing

Open Addressing

To probe ::= to look at an entry and compare its key with target

Linear probing : hi(key) = (h 0 (key) + i) mod M do a linear search from h 0 (key) until you find an empty slot (see Fig. 8.6, compare against Fig. 8.4)

Clustering: when contiguous bins are all occupied Why is clustering undesirable?

Assuming input size N , table size 2 N : What is the best-case cluster distribution? What is the worst-case cluster distribution? What’s the average time to find an empty slot in both cases?

Open Addressing (cont)

Quadratic probing : hi(key) = (h 0 (key) + i^2 ) mod M less likely to form clusters, but only works when table is less than half full because it cannot hit every possible table address

Double hashing : hi(key) = (h(key) + ih′(key)) mod M use 2 distinct hash functions

Removal on scatter tables: complicated, don’t want to move an element up the table beyond its actual hash location; must rehash the rest of chain/cluster, or otherwise mark deleted entry as “deleted” (see Fig. 8.5)