


Study with the several resources on Docsity
Earn points by helping other students or get them with a premium plan
Prepare for your exams
Study with the several resources on Docsity
Earn points to download
Earn points by helping other students or get them with a premium plan
An explanation of hash tables using buckets, a combination of an array and a linked list. It covers the concepts, algorithms for adding, containing, and removing elements, load factor, and resizing the table. The document also includes exercises for further exploration.
Typology: Exams
1 / 4
This page cannot be seen from the preview
Don't miss anything!



In the previous lesson you learned about the concept of hashing, and how it was used in an open address hash table. In this lesson you will explore a different approach to dealing with collisions, the idea of hash tables using buckets. A hash table that uses buckets is really a combination of an array and a linked list. Each element in the array (the hash table) is a header for a linked list. All elements that hash into the same location will be stored in the list. Each operation on the hash table divides into two steps. First, the element is hashed and the remainder taken after dividing by the table size. This yields a table index. Next, linked list indicated by the table index is examined. The algorithms for the latter are very similar to those used in the linked list. For example, to add a new element is simply the following: void HashTableAdd (struct hashTable &ht, EleType newValue) { // compute hash value to find the correct bucket long hash = HASH(newValue); int hashIndex = (int) (labs(hash) % ht.tablelength); listAdd(&ht->table[hashIndex], newValue) dataCount++; // Note: later might want to add resizing the table (below) } The contains test is performed using the list contains function in the appropriate bucket. The removal operation is similar, but should only decrement the item count if the value was actually removed from the list. This ensures the count is accurate. An alternative implementation of the size method would have been to loop over the buckets, asking each list for its size. What would have been the advantages and disadvantages of this approach? As with open address hash tables, the load factor (l) is defined as the number of elements divided by the table size. In this structure the load factor can be larger than one, and represents the average number of elements stored in each list, assuming that the hash function distributes elements uniformly over all positions. Since the running time of the contains test and removal is proportional to the length of the list, they are O(l). Therefore the execution time for hash tables is fast only if the load factor remains small. A typical technique is to resize the table (doubling the size, as with the vector and the open address hash table) if the load factor becomes larger than 10. Complete the implementation of the HashTable class based on these ideas.
struct hashTable { struct list * table; int count; int tablesize; }; void initHashTable (struct hashTable &ht, int tableSize) { } int hashTableSize (struct hashTable *ht) { return ht->count; } void HashTableAdd (struct hashTable *ht, EleType newValue) { // compute hash value to find the correct bucket long hash = HASH(newValue); int hashIndex = (int) (labs(hash) % ht.tablelength); listAdd(&ht->table[hashIndex], newValue); dataCount++; } int hashTableContains (struct hashTable *ht, EleType testElement) { } void hashTableRemove (struct hashTable *ht, EleType testElement) {