Python字典查找算法如何在内部工作?
mydi['foo']
如果字典有1,000,000个术语,是否执行了树搜索?我是否期望在关键字符串的长度或字典的大小方面表现?也许将所有内容都填入字典中就像为500万字符串的字符串编写树搜索索引一样好吗?
答案 0 :(得分:16)
这里有一些伪代码更接近实际发生的事情。想象一下,字典有data
属性,包含键,值对和size
,它是分配的单元格数。
def lookup(d, key):
perturb = j = hash(key)
while True:
cell = d.data[j % d.size]
if cell.key is EMPTY:
raise IndexError
if cell.key is not DELETED and (cell.key is key or cell.key == key):
return cell.value
j = (5 * j) + 1 + perturb
perturb >>= PERTURB
perturb
值确保在解析散列冲突时最终使用散列码的所有位,但一旦降级为0,(5*j)+1
最终将触及表中的所有单元格。
size
总是远大于实际使用的单元格数,因此当密钥不存在时(通常应该非常快地命中一个),保证散列最终会命中空单元格。还有一个键的删除值表示一个不应该终止搜索但当前没有使用的单元格。
关于密钥字符串长度的问题,散列字符串将查看字符串中的所有字符,但字符串也有一个用于存储计算散列的字段。因此,如果每次使用不同的字符串进行查找,字符串长度可能会有一个方位,但如果你有一组固定的键并重复使用相同的字符串,则在第一次使用后不会重新计算哈希值。 Python从中获益,因为大多数名称查找涉及字典,并且每个变量或属性名称的单个副本都存储在内部,因此每次访问属性x.y
时都会进行字典查找,但不会调用哈希功能
答案 1 :(得分:6)
正如您在标题中提到的,dicts是哈希表。不使用树搜索。无论字典大小如何,查找键都是一个几乎恒定的时间操作。
您可能会发现此问题的答案有用:How are Python's Built In Dictionaries Implemented
答案 2 :(得分:5)
以下是一个很好的解释:http://wiki.python.org/moin/DictionaryKeys
来自以上链接的伪代码:
def lookup(d, key):
'''dictionary lookup is done in three steps:
1. A hash value of the key is computed using a hash function.
2. The hash value addresses a location in d.data which is
supposed to be an array of "buckets" or "collision lists"
which contain the (key,value) pairs.
3. The collision list addressed by the hash value is searched
sequentially until a pair is found with pair[0] == key. The
return value of the lookup is then pair[1].
'''
h = hash(key) # step 1
cl = d.data[h] # step 2
for pair in cl: # step 3
if key == pair[0]:
return pair[1]
else:
raise KeyError, "Key %s not found." % key
答案 3 :(得分:1)
散列查找不使用树。他们使用哈希表,并且他们需要持续时间查找。他们将占用更多的空间(平均而言我相信两倍),但查找和插入时间都是胜利。
要过度简化,请使用密钥的md5,然后使用您拥有的地址数量对其进行修改,这就是您保存或查找密钥的位置。无论集合有多大,只要你没有明显的冲突就会花费相同的时间,好的哈希会避免这种冲突。
答案 4 :(得分:0)
答案1:此video
中解释了内部工作答案2:不,如果字典中有一百万条记录,则不会进行树搜索。
答案3:由于可能存在关键冲突,因此您会期望在字典大小方面表现出色,而不是根据密钥字符串的长度。
答案4:将字典视为一个数组(连续的内存位置),但数组中可能存在未使用的块。因此,与树相比,字典倾向于浪费大量的存储空间。但是,为了获得更好的运行时性能,字典可能比树更好。关键冲突有时会降低性能。你应该阅读有关Consistent Hashing的内容。