#ifndef _hashtable_h |
#define _hashtable_h |
|
|
#include "student.h" |
/* |
Hash table of student records. |
|
The hash table is implemented using collision lists. Each collision |
list contains all the student info records whose id hashes to the same |
index value. |
|
NOTE: we manipulate and store actual student records in the hash table, |
not pointers to the records. |
*/ |
|
typedef struct ht_node { |
student_info item; |
struct ht_node *next; |
} ht_node; |
|
typedef struct { |
/* items in the table are placed into buckets, each bin holding items with |
the same hash index */ |
ht_node **buckets; |
int num_buckets; |
} ht_table_instance; |
|
typedef ht_table_instance *hashtable; |
|
/* |
Constructor: create a hash table that will contain roughly size_hint |
items and return a pointer to the instance. |
*/ |
hashtable ht_create(int size_hint); |
|
/* |
Destructor: release all the storage used by the hash table. |
*/ |
void ht_destroy(hashtable h); |
|
/* |
Insert the given item into the hash table using id as the key. |
If an item already exists in the table with the same id, replace |
it with this new one. |
*/ |
void ht_insert(hashtable h, student_info item); |
|
/* |
Lookup the student info item that matches the given id. |
|
If present, return it in the struct pointed to by itemp, and |
return 1. |
|
If missing, don't modify the item, and return 0. |
*/ |
int ht_lookup(hashtable h, int id, student_info *itemp); |
|
|
#endif |
#include "hashtable.h" |
#include <stdlib.h> |
#include <assert.h> |
|
/* |
A very simple hash function |
*/ |
int ht_hash(hashtable ht, int id) { |
return id % ht->num_buckets; |
} |
|
hashtable ht_create(int size_hint) |
{ |
int num_buckets = size_hint; |
hashtable ht = (hashtable) malloc(sizeof(ht_table_instance)); |
assert(ht); |
|
ht->num_buckets = num_buckets; |
ht->buckets = (ht_node **) malloc(sizeof(ht_node *) * ht->num_buckets); |
assert(ht->buckets); |
|
/* Initialize linked lists to NULL */ |
for(int i=0; i < ht->num_buckets; i++) { |
ht->buckets[i] = NULL; |
} |
|
return ht; |
} |
|
void ht_insert(hashtable ht, student_info item) { |
// what index in the table does it hash to? |
int index = ht_hash(ht, item.id); |
|
// empty position |
if ( ! ht->buckets[index] ) { |
// empty list, just place it there */ |
ht_node *n = (ht_node *) malloc(sizeof(ht_node)); |
assert(n); |
n->item = item; |
n->next = 0; |
ht->buckets[index] = n; |
return; |
} |
|
// collision, insert into the list if not already there |
ht_node *cur = ht->buckets[index]; |
while (cur) { |
if ( (cur->item).id == item.id ) { |
// already in table, replace it |
cur->item = item; |
cur = 0; |
} else if ( cur->next ) { |
// no match, but more to look at, move on |
cur = cur->next; |
} else { |
// no match, at end of list, insert at end |
ht_node *n = (ht_node *) malloc(sizeof(ht_node)); |
assert(n); |
cur->next = n; |
n->item = item; |
n->next = 0; |
cur = 0; |
} |
} |
} |
|
int ht_lookup(hashtable ht, int id, student_info *itemp) { |
int index = ht_hash(ht, id); |
|
if ( ! ht->buckets[index] ) { |
// empty list, not present |
return 0; |
} |
|
// walk along collision list looking for matching id |
ht_node *cur = ht->buckets[index]; |
while (cur) { |
if ( (cur->item).id == id ) { |
// found it, return the item and success |
*itemp = cur->item; |
return 1; |
} |
|
// no match, more to look at, move on |
cur = cur->next; |
} |
|
// could not find it |
return 0; |
} |
|
void ht_destroy(hashtable ht) { |
/* unimplemented stub */ |
} |
#include "hashtable.h" |
#include <stdio.h> |
|
void lookup_test(hashtable ht, int test_id) { |
student_info s; |
if (ht_lookup(ht, test_id, &s) ) { |
printf("Id %d has id %d, name %s, grade %s\n", |
test_id, s.id, s.name, s.grade); |
} |
else { |
printf("Id %d not found in hash table\n", test_id); |
} |
} |
|
|
/* our test data */ |
student_info students[] = { |
{ 451241, "Marjorie G. Smith", "B+" }, |
{ 519244, "Michael P. Anderson", "C", }, |
{ 129426, "Ben E. Harrison", "A-" }, |
{ 743295, "William A. Leslie", "B-" }, |
{ 623599, "Brenda M. Crumble", "A+" }, |
{ 195151, "Mary M. Toney", "A-" }, |
}; |
int num_students = 6; |
|
int test_ids[] = { |
195151, 519244, 666222, |
}; |
int num_test_ids = 3; |
|
int main(int argc, char *argv[]) { |
// need to know implementation to realise that size 3 will create collisions |
hashtable ht = ht_create(3); |
|
// how test collisions? |
for (int i=0; i < num_students; i++) { |
ht_insert(ht, students[i]); |
} |
|
for (int i=0; i < num_test_ids; i++) { |
int test_id = test_ids[i]; |
lookup_test(ht, test_id); |
} |
|
// how would you test this? |
ht_destroy(ht); |
} |