The following hashing function is provided:
_hash_key(key)
- takes in a
stringargumentkey - returns a hashed
integervalue unique to the key.
The _hash_key() function implements the rolling polynomial algorithm:
where
-
key- each key segment is a string. It needs to be converted to its integer ASCII value -
p- a small prime number (if the input is composed of only lowercase letters of the English alphabet,$p = 31$ is a good choice. If the input may contain both uppercase and lowercase letters, then$p = 53$ is a possible choice.) -
m- a large prime number (we will use$10^9+9$ for this implementation)
Further learning: [ChatGPT] "What hashing functions are commonly used for hash tables?"
In hashtable.py, implement the HashTable class:
__init__.pyshould take asizeparameter that determines the number of slots that the hashtable is initialised with.- the fixed-size array that holds key-value pairs is represented as a Python
list, pre-filled withNonevalues - do not use
list-mutating methods and operators, such aslist.append(),list.extend(), and list concatenation
and the following methods:
setitem(key, value)- if the hashed location is empty, store the value
- if the hashed location is occupied, overwrite the value
getitem(key)- returns the following:- if the hashed location is empty, the key is not found; raise a
KeyError - if the hashed location is occupied, return the value
- if the hashed location is empty, the key is not found; raise a
delitem(key)- if the hashed location is empty, the key is not found; raise a
KeyError - if the hashed location is occupied, replace the value with
None
- if the hashed location is empty, the key is not found; raise a
- Instantiate a
HashTablewith 15 slots. - Extract the records from the
student_data.csvfile into a list of dicts. - Add each record into the hash table, with the id (i.e.
"s0011a") as the key, and the record (i.e.{"id": "s0011a", "name": "Patrick Tan", "class": "2599"}) as the value - Inspect the fixed-size array and the hashtable length: do they tally?
Linear probing is an open-addressing collision resolution technique in hash tables where, upon a collision, the algorithm checks sequential slots (i + 1, i + 2, ...) linearly until an empty slot is found.
In hashtable.py, implement the HashTableLinearProbing class with the following methods:
setitem(key, value)- if the hashed location is empty, store the key and value
- if the hashed location is occupied and the key matches, store the key and value
- if the hashed location is occupied and the key does not match, re-hash the key (using linear probing) and repeat from (1)
getitem(key)- returns the following:- if the hashed location is empty, the key is not found; raise a
KeyError - If the hashed location is occupied and the key matches, retrieve and return the value
- If the hashed location is occupied and the key does not match, re-hash the key (using linear probing) and repeat from (1)
- if the hashed location is empty, the key is not found; raise a
delitem(key)- if the hashed location is empty, the key is not found; raise a
KeyError - If the hashed location is occupied and the key matches, remove the stored key-value pair. (Note: This will break linear probing for subsequent entries; those will need to be re-inserted)
- If the hashed location is occupied and the key does not match, re-hash the key (using linear probing) and repeat from (1)
- if the hashed location is empty, the key is not found; raise a
In main.py, inspect the fixed-size array and the hashtable length: do they tally now?
Further learning: [ChatGPT] "With open addressing for hash tables, removing key-value pairs can break subsequent probing. What strategies are commonly used to address this?"
Separate chaining is a collision resolution technique in hash tables where multiple elements mapping to the same hash index (bucket) are stored together using an auxiliary data structure, typically a linked list.
In hashtable.py, implement the HashTableSeparateChaining class:
- Instead of initialising the fixed-size array with
Nonevalues, initialise a linked list in each array cell. - You may wish to copy your
LinkedListcode from the previous exercise. Note thatNodewill store akeyand avalueattribute in addition tonext.
Implement the following HashTableSeparateChaining methods:
setitem(key, value)- Walk the linkedlist at the hashed location.
- If the key is found in the linkedlist, update the value at the node where it is found.
- If the key is not found in the linkedlist, add a new node with the key-value pair.
getitem(key)- returns the following:- Walk the linkedlist at the hashed location
- If the key is found in the linkedlist, retrieve and return the value from the node where it is found.
- If the key is not found in the linkedlist, raise a
KeyError.
delitem(key)- Walk the linkedlist at the hashed location
- If the key is found in the linkedlist, unlink the node where it is found.
- If the key is not found in the linkedlist, raise a
KeyError.
In main.py, inspect the fixed-size array and the hashtable length: do they tally now?
Further learning: [ChatGPT] "What are some commonly used ways to resolve collisions in a hash table?"