Hash Tables
LAST TODAY NEXT • Client vs library interface Hashing Making • Implementing hash table dictionaries Genericity code generic
� Hashing fruit — You are the client entries key hash value operations 🍏 “apple” -1290151091 1. insert 0xA0 0xA0: “apple”, 20 “berry” -514151789 2. insert 0xB0 🍔 0xB0: 🍍 3. insert 0xC0 “banana” 207055587 “banana”, 10 🎄 “pumpkin” -1189657311 4. lookup “apple” 0xC0: “pumpkin”, 50 🍈 “grape” -581390202 5. lookup “lime” 0xD0: 🍌 “banana”, 20 “lemon” -665562942 6. insert 0xD0 0xE0: 7. insert 0xE0 2086736531 “lime” “lemon”, 5
Library Interface Client Interface // typedef ______ key; // typedef ______* hdict_t; // typedef ______* entry; hdict_t hdict_new(int capacity) /*@requires capacity > 0; @*/ /*@ensures \result != NULL; @*/ ; key entry_key(entry x) /*@requires x != NULL; @*/ ; entry hdict_lookup(hdict_t H, key k) /*@requires H != NULL; @*/ int key_hash(key k); bool key_equiv(key k1, key k2); void hdict_insert(hdict_t H, entry x) /*@requires H != NULL && x != NULL; @*/
// typedef ______* entry; // typedef ______ key; Library interface key entry_key(entry x) /*@requires x != NULL; @*/ ; int key_hash(key k); bool key_equiv(key k1, key k2); // typedef ______* hdict_t; hdict_t hdict_new(int capacity) /*@requires capacity > 0; @*/ /*@ensures \result != NULL; @*/ ; entry hdict_lookup(hdict_t H, key k) client-side types /*@requires H != NULL; @*/ void hdict_insert(hdict_t H, entry x) /*@requires H != NULL && x != NULL; @*/ What about postconditions?
// typedef ______* entry; // typedef ______ key; Library interface key entry_key(entry x) /*@requires x != NULL; @*/ ; int key_hash(key k); bool key_equiv(key k1, key k2); // typedef ______* hdict_t; hdict_t hdict_new(int capacity) /*@requires capacity > 0; @*/ /*@ensures \result != NULL; @*/ ; entry hdict_lookup(hdict_t H, key k) /*@requires H != NULL; @*/ /*@ensures \result == NULL || key_equiv(entry_key(\result), k); @*/ ; void hdict_insert(hdict_t H, entry x) /*@requires H != NULL && x != NULL; @*/
// typedef ______* entry; // typedef ______ key; Library interface key entry_key(entry x) /*@requires x != NULL; @*/ ; int key_hash(key k); bool key_equiv(key k1, key k2); // typedef ______* hdict_t; hdict_t hdict_new(int capacity) /*@requires capacity > 0; @*/ /*@ensures \result != NULL; @*/ ; entry hdict_lookup(hdict_t H, key k) /*@requires H != NULL; @*/ /*@ensures \result == NULL || key_equiv(entry_key(\result), k); @*/ ; void hdict_insert(hdict_t H, entry x) /*@requires H != NULL && x != NULL; @*/ /*@ensures hdict_lookup(H, entry_key(x)) == x; @*/ ;
Code organization Client implementation (HOW) Client interface (WHAT) Library implementation (HOW) Library interface (WHAT) Client application
Library code /************************/ Client interface /*** Client interface ***/ /************************/ (WHAT) /**************************/ Library implementation /* Library implementation */ (HOW) /**************************/ Library interface /************************/ (WHAT) /** Library interface ***/ /************************/
coin hdict.c0 hdict.c0:18.1-18.4:error:identifier 'key' at top level Need to compile in this order: cc0 -d lib/*.c0 produce.c0 hdict.c0 produce-test.c0 client implementation
Client Implementation: fulfilling the client interface ( produce.c0 ) using the dictionary ( produce-test .c0 )
Library Implementation: structure definitions, data structure invariants
0 1 2 3 4 typedef struct chain_node chain; struct chain_node { ____ data; // != NULL; contains both key and value entry ____ next; chain* };
0 1 2 3 4 typedef struct chain_node chain; struct chain_node { ____ data; // != NULL; contains both key and value entry ____ next; chain* }; typedef struct hdict_header hdict; struct hdict_header { int size; // 0 <= size _______ table; // \length(table) == capacity chain*[] int capacity; // 0 < capacity };
Data (representation) structure invariant bool is_array_expected_length(chain*[] table, int length) { //@assert \length(table) == length; return true; } bool is_hdict(hdict* H) { return H != NULL && H->capacity > 0 && H->size >= 0 && is_array_expected_length(H->table, H->capacity); /* && other properties*/ } Can the client violate is_hdict?
typedef struct chain_node chain; struct chain_node { entry data; chain* next; }; typedef struct hdict_header hdict; struct hdict_header { int size; chain*[] table; hdict* hdict_new(int capacity) int capacity; }; //@requires capacity > 0; //@ensures is_hdict(\result); { hdict* H = _____________ alloc(hdict); H->size = 0; H->capacity = capacity; H->table = ____________________________ alloc_array(chain*, capacity); return H; }
entry hdict_lookup(hdict* H, key k) //@requires is_hdict(H); //@ensures \result == NULL || key_equiv(entry_key(\result), k); { int i = index_of_key(H, k); for (chain* p = H->table[i]; p != NULL; p = p->next) { if (key_equiv(entry_key(p->data), k)) return p->data; } return NULL; }
Hash sets • Insert is adding an member to a set • lookup is a membership check • (key = entry = set member)
Recommend
More recommend