Implementing Hash Tables Hash tables array implementation z
Implementing Hash Tables
Hash tables - array implementation z // for an array implementation, need a max table size z const int MAX_TABLE = 11;
Table class, public section z template < class table. Key. Type, class table. Data. Type > z class Table z { public: z Table(); // Table constructor z void insert(const table. Key. Type & key, const table. Data. Type & data); z // Precondition: None z // Postcondition: data and key are stored in the Table, z // i. e. , lookup(key, data) == true and returns the data z // Note: If data already stored with this key, replace it.
Table class, lookup(), z bool lookup(const table. Key. Type & key, table. Data. Type & data); z // Precondition: None z // Postcondition: if key in table, returns true and associated z // data is returned; otherwise, false is returned and z // data is undefined.
delete. Key(), dump() z void delete. Key(const table. Key. Type & key); z // Precondition: None z // Postcondition: lookup(key, d) returns false z void dump(); // print the contents of the hash table -- handy!
Table class, private section z private: z // implementation via a hash table z enum slot. Type {Empty, Deleted, In. Use}; z struct slot { z slot. Type slot. Status; z table. Key. Type key; z table. Data. Type data; z }; z slot T[MAX_TABLE]; // stores the items in the table z int entries; // keep track of number of entries in table
Hash Table T Array of slots entries slot. Status key data
Private, hash() z int hash(const table. Key. Type & key); z // Precondition: none z // Postcondition: none z // Returns: the home address for key
Private, probe(), search() z int probe(const int pos); z // Precondition: pos is a slot between 0 and MAX_TABLE-1 z // Postcondition: none z // Returns: the next slot, using wrapping (between 0 and MAX_TABLE-1) z z bool search(int & pos, const table. Key. Type & target); z // Precondition: pos is the hash address of target z // Postcondition: if target is in table, pos is set to its actual slot z // Returns: true if target is in the table, else false z };
hash() implementation z template < class table. Key. Type, class table. Data. Type > z int Table < table. Key. Type, table. Data. Type > z : : hash(const table. Key. Type & key) z{ z return key % MAX_TABLE; z}
probe() implementation z template < class table. Key. Type, class table. Data. Type > z int Table < table. Key. Type, table. Data. Type > z : : probe(const int pos) z{ z if (pos < MAX_TABLE - 1) z return pos + 1; z else z return 0; z}
search() implementation z template < class table. Key. Type, class table. Data. Type > z bool Table < table. Key. Type, table. Data. Type > z : : search(int & pos, const table. Key. Type & target) z { // search for target, starting at pos z for ( ; T[pos]. slot. Status != Empty; pos = probe(pos)) z if (T[pos]. slot. Status == In. Use && T[pos]. key == target) z return true; z return false; z}
Constructor implementation z template < class table. Key. Type, class table. Data. Type > z Table < table. Key. Type, table. Data. Type > z : : Table() // implementation of Table constructor z{ z entries = 0; z int i; z for (i = 0; i < MAX_TABLE; i++) z T[i]. slot. Status = Empty; z}
Insert() implementation z template < class table. Key. Type, class table. Data. Type > z void Table < table. Key. Type, table. Data. Type > z : : insert(const table. Key. Type & key, const table. Data. Type & data) z { assert(entries < MAX_TABLE - 1); z int pos(hash(key)); // find a position to insert the item z if (!search(pos, key)) { // key was not in the table z pos = hash(key); // find first free position z while (T[pos]. slot. Status == In. Use) z pos = probe(pos); z entries++; // number of entries goes up z }
Insert() (continued) z T[pos]. slot. Status = In. Use; z T[pos]. key = key; z T[pos]. data = data; z}
lookup() implementation z template < class table. Key. Type, class table. Data. Type > z bool Table < table. Key. Type, table. Data. Type > z : : lookup(const table. Key. Type & key, table. Data. Type & data) z { int pos(hash(key)); z if (search(pos, key)) { z data = T[pos]. data; z return true; z } z else z return false; }
delete. Key() implementation z template < class table. Key. Type, class table. Data. Type > z void Table < table. Key. Type, table. Data. Type > : : delete. Key(const table. Key. Type & key) z{ z int pos(hash(key)); z if (search(pos, key)) { z T[pos]. slot. Status = Deleted; z entries--; z } z}
dump() implementation z // the following function is handy for debugging z template < class table. Key. Type, class table. Data. Type > z Void Table < table. Key. Type, table. Data. Type >: : dump() z { int i; z for (i = 0; i < MAX_TABLE; i++) { z cout << i << 't'; z switch(T[i]. slot. Status) { z case In. Use: z cout << "In Uset" << T[i]. key << endl; z break;
dump(), continued z case Deleted: z cout << "Deletedt" << T[i]. key << endl; z break; z case Empty: z cout << "Emptyt" << endl; z break; z } z cout << "Entries = " << entries << "nn"; z}
Chained hashing
Figure 10 -8: Chained hashing
Hash table class definition z template < class table. Key. Type, class table. Data. Type > z class Table z { public: z Table(); // Table constructor z void insert(const table. Key. Type & key, const table. Data. Type & data); z // Precondition: None z // Postcondition: data and key are stored in the Table, z // i. e. , lookup(key, data) == true and returns the data z // Note: If data already stored with this key, the insert z // call will replace it.
Public section (continued) z bool lookup(const table. Key. Type & key, table. Data. Type & data); z // Precondition: None z // Postcondition: if key in table, returns true and associated z // data is returned; otherwise, false is returned and z // data is undefined. z void delete. Key(const table. Key. Type & key); z // Precondition: None z // Postcondition: lookup(key, d) returns false z void dump(); // print the contents of the hash table
Private section z private: z // implementation via a hash table z struct Slot; z typedef Slot * Link; z struct Slot { z table. Key. Type key; z table. Data. Type data; z Link next; z }; z Link T[MAX_TABLE]; // table is an array of pointers to slots z
Private section (continued) z int hash(const table. Key. Type & key); z // Precondition: none z // Postcondition: none z // Returns: the home address for key z bool search(Link & slot. Pointer, const table. Key. Type & target); z // Precondition: slot. Pointer points to the start of the chain for z // target's hash address z // Postcondition: if target is in the chain, slot. Pointer points to it z // Returns: true if target is in the table, else false z };
hash() implementation z template < class table. Key. Type, class table. Data. Type > z int z Table < table. Key. Type, table. Data. Type > z : : hash(const table. Key. Type & key) z{ z return key % MAX_TABLE; z}
Search() implementation z template < class table. Key. Type, class table. Data. Type > z bool Table < table. Key. Type, table. Data. Type > z : : search(Link & slot. Pointer, const table. Key. Type & target) z{ z // search for target, starting at slot. Pointer z for ( ; slot. Pointer = slot. Pointer -> next) z if (slot. Pointer->key == target) z return true; z return false; z}
Table constructor z template < class table. Key. Type, class table. Data. Type > z Table < table. Key. Type, table. Data. Type > z : : Table() // implementation of Table constructor z { int i; z for (i = 0; i < MAX_TABLE; i++) z T[i] = 0; z}
Insert() implementation z template < class table. Key. Type, class table. Data. Type > z void Table < table. Key. Type, table. Data. Type > z : : insert(const table. Key. Type & key, const table. Data. Type & data) z { int pos(hash(key)); // find a position to insert the item z Link sp(T[pos]); z
Insert() continued z if (!search(sp, key)) { // key was not in the table z // insert new item at beginning of list z Link inserted. Slot = new Slot; z inserted. Slot->key = key; z inserted. Slot->data = data; z inserted. Slot->next = T[pos]; z T[pos] = inserted. Slot; z } z else // found old record -- update the data z sp->data = data; z}
lookup() implementation z template < class table. Key. Type, class table. Data. Type > z bool Table < table. Key. Type, table. Data. Type > z : : lookup(const table. Key. Type & key, table. Data. Type & data) z { int pos(hash(key)); z Link sp(T[pos]); z if (search(sp, key)) { z data = sp->data; z return true; } z else z return false; z}
delete. Key() implementation z template < class table. Key. Type, class table. Data. Type > z void z Table < table. Key. Type, table. Data. Type >: : delete. Key(const table. Key. Type & key) z { // need to find pointer to item preceding the slot to delete z int pos(hash(key)); z Link p; z if (T[pos] == 0) return; // there's no list for this slot z if (T[pos]->key == key) { // special case, first item in chain z Link delete. Slot(T[pos]); z T[pos] = T[pos]->next; z delete. Slot; }
delete. Key() (continued) z else z for (p = T[pos]; p->next; p = p->next) z if (p->next->key == key) { z Link delete. Slot = p->next; z p->next = p->next; z delete. Slot; z break; z } z}
dump() implementation z template < class table. Key. Type, class table. Data. Type > z void Table < table. Key. Type, table. Data. Type >: : dump() z { int i; z for (i = 0; i < MAX_TABLE; i++) { z cout << i << 't'; z Link p; z for (p = T[i]; p; p = p->next) z cout << p->key << 't'; z cout << 'n'; z } z cout << 'n'; z}
Chapter Summary z. The Table ADT supports insertion and retrieval via a key. z. A straight forward implementation of the table as an array doesn’t have desirable performance characteristics. z. Hashing can be used to build tables with rapid insertion and retrieval.
Chapter summary (con’t) z. Division hashing is one approach to creating a hash function. z. Collisions result when two keys have the same hash address. z. Chaining is an alternative to probing. z. Hashing is used for data processing, compilers, networking, and other applications.
- Slides: 36