# -*- coding: utf-8 -*-

class Array(object):

    def __init__(self, size=32, init=None):
self._size = size
self._items = [init] * size def __getitem__(self, index):
return self._items[index] def __setitem__(self, index, value):
self._items[index] = value def __len__(self):
return self._size def clear(self, value=None):
for i in range(len(self._items)):
self._items[i] = value def __iter__(self):
for item in self._items:
yield item class Slot(object): def __init__(self, key, value):
self.key, self.value = key, value class HashTable(object): UNUSED = None # 没被使用过
EMPTY = Slot(None, None) # 使用却被删除过 def __init__(self):
self._table = Array(8, init=HashTable.UNUSED) # 保持 2*i 次方
self.length = 0 @property
def _load_factor(self):
# load_factor 超过 0.8 重新分配
return self.length / float(len(self._table)) def __len__(self):
return self.length def _hash(self, key):
return abs(hash(key)) % len(self._table) def _find_key(self, key):
index = self._hash(key)
_len = len(self._table)
while self._table[index] is not HashTable.UNUSED:
if self._table[index] is HashTable.EMPTY:
index = (index*5 + 1) % _len
continue
elif self._table[index].key == key:
return index
else:
index = (index*5 + 1) % _len
return None def _find_slot_for_insert(self, key):
index = self._hash(key)
_len = len(self._table)
while not self._slot_can_insert(index):
index = (index*5 + 1) % _len
return index def _slot_can_insert(self, index):
return (self._table[index] is HashTable.EMPTY or self._table[index] is HashTable.UNUSED) def __contains__(self, key): # in operator
index = self._find_key(key)
return index is not None def add(self, key, value):
if key in self:
index = self._find_key(key)
self._table[index].value = value
return False
else:
index = self._find_slot_for_insert(key)
self._table[index] = Slot(key, value)
self.length += 1
if self._load_factor >= 0.8:
self._rehash()
return True def _rehash(self):
old_table = self._table
newsize = len(self._table) * 2
self._table = Array(newsize, HashTable.UNUSED) self.length = 0 for slot in old_table:
if slot is not HashTable.UNUSED and slot is not HashTable.EMPTY:
index = self._find_slot_for_insert(slot.key)
self._table[index] = slot
self.length += 1 def get(self, key, default=None):
index = self._find_key(key)
if index is None:
return default
else:
return self._table[index].value def remove(self, key):
index = self._find_key(key)
if index is None:
raise KeyError()
value = self._table[index].value
self.length -= 1
self._table[index] = HashTable.EMPTY
return value def __iter__(self):
for slot in self._table:
if slot not in (HashTable.EMPTY, HashTable.UNUSED):
yield slot.key def test_hash_table():
h = HashTable()
h.add('a', 0)
h.add('b', 1)
h.add('c', 2)
assert len(h) == 3
assert h.get('a') == 0
assert h.get('b') == 1
assert h.get('hehe') is None h.remove('a')
assert h.get('a') is None
assert sorted(list(h)) == ['b', 'c'] n = 50
for i in range(n):
h.add(i, i) for i in range(n):
assert h.get(i) == i if __name__ == '__main__':
print(
'beg',
test_hash_table(),
'end',
)

最新文章

  1. HUST 1017 - Exact cover (Dancing Links 模板题)
  2. grep与egrep
  3. my class 2.0
  4. C# string格式的日期时间字符串转为DateTime类型
  5. jquery ztree插件
  6. php 字母大小写转换的函数
  7. Cocos2d-x响应android返回键
  8. 利用自定义的AuthenticationFilter实现Basic认证
  9. USACO Section 1.2 Name That Number 解题报告
  10. [USACO12FEB]Nearby Cows
  11. 基于hi-nginx的web开发(python篇)——cookie和会话管理
  12. kv_storage.go
  13. Pickup Objective Actor
  14. cxf 动态调用.
  15. IntelliJ IDEA 2017版 spring-boot使用Spring Data JPA搭建基础版的三层架构
  16. [你必须知道的.NET]第十八回:对象创建始末(上)
  17. 使用OpenSSL(Windows x64版)将pem格式证书转换为p12格式
  18. (1)分布式下的爬虫Scrapy应该如何做-安装
  19. canvas动态绘制饼状图,
  20. ssh连接github连不上

热门文章

  1. C罗是你人生中最好的健身教练和精神导师
  2. 编译Cython代码时遇到的问题: fatal error LNK1112: module machine type 'x64' conflicts with target machine type 'X86'
  3. JVM(三) 对象的创建过程
  4. Ubuntu 中改变文件的默认打开方式(转)
  5. 【转帖】为什么redis 是单线程的?
  6. Struts笔记5
  7. [C++] 例题 2.7.1 用栈实现简易计算器
  8. Spyder中报错: Check failed: PyBfloat16_Type.tp_base != nullptr
  9. PAT(B) 1063 计算谱半径(Java)
  10. 【自学系列一】HTML5大前端学习路线+视频教程(完整版)