Advertisement
cyga

HashMap for OOP interview

Dec 4th, 2021
906
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 3.14 KB | None | 0 0
  1. """ HashMap implementation. """
  2. from typing import Any
  3. import abc
  4.  
  5. class Error(Exception):
  6.     """ Base class for custom exceptions raised by this module """
  7.  
  8. class NoSuchKeyError(Error):
  9.     """ No such key exception. """
  10.  
  11. class EmptyCapacityError(Error):
  12.     """ Empty capacity for the hash map exception. """
  13.  
  14. class HashMapBase(abc.ABC):
  15.     """ Base class for hash map implementations. It defines API. """
  16.     @abc.abstractmethod
  17.     def __init__(self, **opts):
  18.         if 'capacity' in opts:
  19.             self.capacity = opts['capacity']
  20.     @abc.abstractmethod
  21.     def get(self, key: Any) -> Any:
  22.         """ Gets value for the specified key. """
  23.     @abc.abstractmethod
  24.     def set(self, key: Any, value: Any) -> None:
  25.         """ Sets value for the specified key. """
  26.     @abc.abstractmethod
  27.     def exists(self, key: Any) -> bool:
  28.         """ Checks if the given key exists in the hash map. """
  29.     @abc.abstractmethod
  30.     def remove(self, key: Any) -> None:
  31.         """ Removes the specified key from hash map. """
  32.  
  33.     def hash(self, key: Any):
  34.         """ Calculates the hash number for the given key based on the current capacity. """
  35.         if self.capacity == 0:
  36.             return EmptyCapacityError()
  37.  
  38.         return hash(key) % self.capacity
  39.  
  40. class HashMap(HashMapBase):
  41.     """
  42.    One of possible hash map implementations based on closed addressing and list for every cell.
  43.    """
  44.     default_capacity = 1024
  45.  
  46.     def __init__(self, **opts):
  47.         if 'capacity' not in opts:
  48.             opts['capacity'] = self.default_capacity
  49.         super().__init__(**opts)
  50.         self.data = [[] for _ in range(self.capacity)]
  51.  
  52.     def resize(self):
  53.         """
  54.        Resizes object whenever it takes too much or too few space compared to the capacity.
  55.        This allows to keep number of collision and capacity appropriate to the current usage.
  56.        TODO: not implemented yet.
  57.        Most probably, we also need min and max fill factors in constructor for this.
  58.        """
  59.  
  60.     def get(self, key: Any) -> Any:
  61.         hash_value = self.hash(key)
  62.         for cur_key, value in self.data[hash_value]:
  63.             if cur_key == key:
  64.                 return value
  65.         raise NoSuchKeyError()
  66.  
  67.     def exists(self, key: Any) -> bool:
  68.         hash_value = hash(key)
  69.         for cur_key, _ in self.data[hash_value]:
  70.             if cur_key == key:
  71.                 return True
  72.         return False
  73.  
  74.     def set(self, key: Any, value: Any) -> None:
  75.         # call it before set in order to prevent zero capacity problems
  76.         self.resize()
  77.  
  78.         hash_value = self.hash(key)
  79.         for i, (cur_key, _) in enumerate(self.data[hash_value]):
  80.             if cur_key == key:
  81.                 self.data[hash_value][i] = (key, value)
  82.                 return
  83.         self.data[hash_value].append((key, value))
  84.  
  85.     def remove(self, key: Any) -> None:
  86.         hash_value = self.hash(key)
  87.         for i, (cur_key, _) in enumerate(self.data[hash_value]):
  88.             if cur_key == key:
  89.                 del self.data[hash_value][i]
  90.                 self.resize()
  91.                 return
  92.  
  93.         raise NoSuchKeyError()
  94.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement