散列表 / Hash Table


 

散列表与散列函数

散列表是一种将关键字映射到特定数组位置的一种数据结构,而将关键字映射到0至TableSize-1过程的函数,即为散列函数

Hash Table:
        [0] -> A
        [1] -> B
        [2] -> C
        [3] -> D
        [4] -> E

下面以一个简单的散列函数 Hash(Key)=Key mod TableSize为例,完成一个散列表的实现。

Note: 为方便起见,这里选用了一个非素数作为TableSize,适宜的TableSize应为一个素数。

完整代码

  1 from collections import Iterable
  2 
  3 
  4 class CollisionError(Exception):
  5     pass
  6 
  7 
  8 class HashTable:
  9     """
 10     Hash Table:
 11         [0] -> A
 12         [1] -> B
 13         [2] -> C
 14         [3] -> D
 15         [4] -> E
 16     """
 17     def __init__(self, size, fn):
 18         self._array = [None for i in range(size)]
 19         self._hashing = fn
 20 
 21     def __str__(self):
 22         return '\n'.join('[%d] %s' % (index, item) for index, item in enumerate(self._array))
 23 
 24     def find(self, item):
 25         hash_code = self._hashing(item)
 26         value = self._array[hash_code]
 27         return value if value == item else None, hash_code
 28 
 29     def insert(self, *args):
 30         for i in args:
 31             if isinstance(i, Iterable):
 32                 for j in i:
 33                     self._insert(j)
 34             else:
 35                 self._insert(i)
 36 
 37     def _insert(self, item):
 38         if item is None:
 39             return
 40         hash_code = self._hashing(item)
 41         value = self._array[hash_code]
 42         if value is not None and value != item:      # Handle value 0 and value existed situation.
 43             raise CollisionError('Hashing value collided!')
 44         self._array[hash_code] = item
 45 
 46     def delete(self, item):
 47         hash_code = self._hashing(item)
 48         if self._array[hash_code] != item:
 49             raise KeyError('Key error with %s' % item)
 50         self._array[hash_code] = None
 51 
 52     def show(self):
 53         print(self)
 54 
 55     @property
 56     def size(self):
 57         return len(self._array)
 58 
 59     @property
 60     def load_factor(self):
 61         element_num = sum(map(lambda x: 0 if x is None else 1, self._array))
 62         return element_num/self.size
 63 
 64     def make_empty(self):
 65         self._array = [None for i in range(self.size)]
 66 
 67 
 68 def kmt_hashing(size):
 69     # Key = Key mod TableSize
 70     return lambda x: x % size
 71 
 72 
 73 def test(h):
 74     print('\nShow hash table:')
 75     h.show()
 76 
 77     print('\nInsert values:')
 78     h.insert(7, 8, 9)
 79     h.insert(range(7))
 80     h.show()
 81     print('\nInsert values (existed):')
 82     h.insert(1)
 83     h.show()
 84     print('\nInsert value (collided):')
 85     try:
 86         h.insert(11)
 87     except CollisionError as e:
 88         print(e)
 89 
 90     print('\nFind value:')
 91     print(h.find(7))
 92     print('\nFind value (not existed):')
 93     print(h.find(77))
 94 
 95     print('\nDelete value:')
 96     h.delete(7)
 97     h.show()
 98     print('\nDelete value (not existed):')
 99     try:
100         h.delete(111)
101     except KeyError as e:
102         print(e)
103 
104     print('\nLoad factor is:', h.load_factor)
105     print('\nClear hash table:')
106     h.make_empty()
107     h.show()
108 
109 if __name__ == '__main__':
110     test(HashTable(10, kmt_hashing(10)))
View Code

相关文章: