Read chapter 12, sections 2 and 3.
Default function arguments can specify values for function arguments that usually have the same value. For example, the function int foo(int x, int y = 3) can be called using either foo(4,5) or foo(4). In the former case, the parameter values are x = 4 and y = 5. In the latter case, y's parameter value is 3. See also the textbook pp. 60-62.
You are to implement a simple class for hash tables, similar in functionality to the STL hash table You may solve the problem in any way you like, except that you may not use the STL map or hash_map classes. I strongly recommend making use of one of the data structures we have studied and/or implemented in this course.
A hash table is a data structure supporting insertion, removal, and querying of elements in expected constant time by using a hash function. A hash function converts an element into a number specifying where the element should be stored. You are to implement an open-chained hash table using strings as keys. As discussed in class, such a table consists (conceptually) of an array of lists, with one array element for each possible output of the hash function. (Notice that while we can describe this table as an array of lists, we can actually implement it using any convenient data structure, such as the STL vector class.) For simplicity, your hash table need only store keys, rather than key-value pairs as hash tables usually do. (Such a table could still be useful; for example, we could use it to store a mathematical set in such a way that it would be quick to add elements, remove elements, or determine whether a particular element is in the set.)
The hashTable class should support the operations listed in the following table. These operations are similar to but not identical to those provided by the STL hash tables.
Prototype | Example use | Explanation |
---|---|---|
hashTable(void) | hashTable h; | create a hash table with no entries. |
void insert(const string & key); | h.insert("hello"); | add the given key to table if not already present. |
bool query(const string & key) const; | bool b = h.query("goodbye"); | return true if and only if key is in table. |
void remove(const string & key); | h.remove("whatever") | remove key from table, if present. |
friend ostream& operator<<(ostream & out, const hashTable & h); | cout << h; | print hash table's contents, one per line, in no specific order. |
void printInfo(ostream & out) const | printInfo(cout); | print the table plus internal info; see description below. |
Notes:
Table size: 16 Number of keys stored: 4 Contents: data (4) which (7) bye (12) hello (15)
data which bye hello
For the hash table described above, we need a hash function that converts a string to a position in the hash table's main array or vector. There are many possibilities for defining such a function; this section describes (and the starter code implements) one that has proved to work well in practice.
Conceptually, the hash function you will use is a composition of three simpler functions:
A good hash function spreads out a hash table's contents, but if any significant number of table positions have too many entries, using the hash table will take too much time. Conversely, if only a few table positions have any entries at all, the table is probably bigger than it needs to be. Thus, if the hash table becomes too full, we should make the table bigger; if it becomes too close to empty, we should make it smaller. Specifically, if is the size of the main array/vector, and is the number of actual entries (keys stored), we should do the following: If , double the size of the main array/vector. If , halve the size of the main array/vector.
When resizing the hash table, every key in the hash table must be rehashed, since the hash function's values depend on the table's size. One implementation strategy is to insert the keys into a newly created vector. Another strategy is to always have two vectors in the hash table object, plus a variable indicating which vector currently contains the keys. To resize, one can then clear the other vector, resize it to the new size, insert into it all the keys from the vector currently containing the keys, and mark it as the vector currently containing the keys.
You will likely find it easiest to implement your hash table class using STL containers and functions. I suggest representing the table as a vector of vectors of strings. Useful vector functions include the following:
You may want to initially implement your class without resizing, and add that functionality later.
I have provided a skeleton for your hash table class in file hashTable.h, including do-nothing implementations of all the required functions and an almost-complete implementation of the hash function described above. Places where you need to add or change code are indicated by comments of the form ADD YOUR CODE HERE or REPLACE THE FOLLOWING LINE WITH YOUR CODE. I have also provided a program you can use to test your hash table class, test-hashTable.cpp. How the test program works should be fairly obvious if you compile it and execute it; it will compile with the skeleton hash table class, though it doesn't do anything very interesting.
Submit your source code (hashTable.h only) as described in the Guidelines for Programming Assignments. For this assignment use a subject line of ``cs1321 hw0x''.