Hash table using open addressing with linear probing. Examples: >>> ht = HashTable(10) >>> ht.put(1, 'one') >>> ht.get(1) 'one'
| 16 | |
| 17 | |
| 18 | class HashTable: |
| 19 | """Hash table using open addressing with linear probing. |
| 20 | |
| 21 | Examples: |
| 22 | >>> ht = HashTable(10) |
| 23 | >>> ht.put(1, 'one') |
| 24 | >>> ht.get(1) |
| 25 | 'one' |
| 26 | """ |
| 27 | |
| 28 | _empty = object() |
| 29 | _deleted = object() |
| 30 | |
| 31 | def __init__(self, size: int = 11) -> None: |
| 32 | """Initialize the hash table. |
| 33 | |
| 34 | Args: |
| 35 | size: Number of slots in the underlying array. |
| 36 | """ |
| 37 | self.size = size |
| 38 | self._len = 0 |
| 39 | self._keys: list[object] = [self._empty] * size |
| 40 | self._values: list[object] = [self._empty] * size |
| 41 | |
| 42 | def put(self, key: int, value: object) -> None: |
| 43 | """Insert or update a key-value pair. |
| 44 | |
| 45 | Args: |
| 46 | key: The key to insert. |
| 47 | value: The value associated with the key. |
| 48 | |
| 49 | Raises: |
| 50 | ValueError: If the table is full. |
| 51 | """ |
| 52 | initial_hash = hash_ = self.hash(key) |
| 53 | |
| 54 | while True: |
| 55 | if self._keys[hash_] is self._empty or self._keys[hash_] is self._deleted: |
| 56 | self._keys[hash_] = key |
| 57 | self._values[hash_] = value |
| 58 | self._len += 1 |
| 59 | return |
| 60 | elif self._keys[hash_] == key: |
| 61 | self._keys[hash_] = key |
| 62 | self._values[hash_] = value |
| 63 | return |
| 64 | |
| 65 | hash_ = self._rehash(hash_) |
| 66 | |
| 67 | if initial_hash == hash_: |
| 68 | raise ValueError("Table is full") |
| 69 | |
| 70 | def get(self, key: int) -> object | None: |
| 71 | """Retrieve the value for a given key. |
| 72 | |
| 73 | Args: |
| 74 | key: The key to look up. |
| 75 |
no outgoing calls