A symbol table is an unordered collection of bindings. A binding consists of a key and a value. A key is a string that uniquely identifies its binding; a value is data that is somehow pertinent to its key. A symbol table allows its client to insert (put) new bindings, to retrieve (get) the values of bindings with specified keys, and to remove bindings with specified keys. Symbol tables are used often in programming systems; compilers and assemblers use them extensively.
A hash table is a particularly efficient way to implement a symbol table. Section 2.9 of The Practice of Programming (Kernighan and Pike), chapter 8 of C Interfaces and Implementations (Hanson), and chapter 14 of Algorithms in C, Parts 1-4 (Sedgewick) describe hash tables.
Your task in this assignment is to create an ADT named SymTable. Each instance of the SymTable ADT should be a symbol table. You should design your SymTable ADT so it is "generic." That is, you should design your SymTable so its values are void pointers, and thus can point to data of any type.
Subsequent assignments may ask you to create programs that are clients of your SymTable ADT.
The SymTable interface should contain these function declarations:
SymTable_T SymTable_new(void); void SymTable_free(SymTable_T oSymTable); int SymTable_getLength(SymTable_T oSymTable); int SymTable_put(SymTable_T oSymTable, const char *pcKey, const void *pvValue); int SymTable_contains(SymTable_T oSymTable, const char *pcKey); void *SymTable_get(SymTable_T oSymTable, const char *pcKey); int SymTable_remove(SymTable_T oSymTable, const char *pcKey); void SymTable_map(SymTable_T oSymTable, void (*pfApply)(const char *pcKey, void *pvValue, void *pvExtra), const void *pvExtra);The SymTable_new function should return a new SymTable_T that contains no bindings.
The SymTable_free function should free all memory occupied by oSymTable.
The SymTable_getLength function should return the number of bindings in oSymTable. It should be a checked runtime error for oSymTable to be NULL.
The SymTable_put function should add a new binding to oSymTable consisting of key pcKey and value
pvValue. It should return 1 (TRUE) if successful, and 0 (FALSE) otherwise. It
should be a checked runtime error for oSymTable or pcKey to be NULL.
The SymTable_contains function should return 1 (TRUE) if oSymTable contains a binding whose key is
pcKey, and 0 (FALSE) otherwise. It should be a checked runtime error for oSymTable or pcKey to be NULL.
The SymTable_get function should return the value of the binding within oSymTable whose key is pcKey, or NULL if no such binding exists. It should be a checked runtime error for oSymTable or pcKey to be NULL.
The SymTable_remove function should remove from oSymTable the binding whose key is
pcKey. It should return 1 (TRUE) if successful, and 0 (FALSE) otherwise.
It should be a checked runtime error for oSymTable or pcKey to be NULL.
The SymTable_map function should apply function *pfApply to each binding in
oSymTable, passing pvExtra as an extra parameter. It should be a checked runtime error for oSymTable or pfApply to be
NULL.
unsigned int hash(const char *pcKey) /* Return a hash code for pcKey. Adapted from the Fall 2002 COS 217 lecture notes. */ { int i; unsigned int uiHash = 0U; for (i = 0; pcKey[i] != NULL; i++) uiHash = uiHash * 65599 + pcKey[i]; return uiHash; }See page 578 of the Sedgewick textbook for an alternative.
Implementing those features is worth 90% of the assignment. To receive full credit for the assignment, your SymTable implementation should also:
More precisely, page 126 of the Hanson textbook provides a sequence of integers that are appropriate bucket counts: 509, 1021, 2053, 4093, 8191, 16381, 32771, and 65521. When the SymTable_put function detects that the new binding count exceeds 509, it should increase the bucket count to 1021. When the function detects that the new binding count exceeds 1021, it should increase the bucket count to 2053. Etc. When SymTable_put detects that the new binding count exceeds 65521, it should not increase the bucket count. Thus 65521 is the maximum number of buckets that the SymTable should contain.
A minimal test program is available in the file /u/cs217/Assignment2/testsymtable.c. You may use it as a starting point for creating your own test programs.
Create a "readme" text file that contains:
Submit your work electronically on arizona via the command:
/u/cs217/bin/submit 2 symtable.h symtable.c readme
Note: You will receive a better grade if you submit a working non-expanding SymTable ADT instead of a non-working expanding SymTable ADT. If your attempts to develop the expansion code fail, then leave the expansion code in your symtable.c file as comments, and describe your attempts in your readme file.