python 哈希表实现简单python字典代码实例
这篇文章主要介绍了python哈希表实现简单python字典代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
classArray(object): def__init__(self,size=32,init=None): self._size=size self._items=[init]*size def__getitem__(self,index): returnself._items[index] def__setitem__(self,index,value): self._items[index]=value def__len__(self): returnself._size defclear(self,value=None): foriinrange(self,_items): self._items[i]=value def__iter__(self): foriteminself._items: yielditem classSlot(object): """ 定义一个哈希表数组的槽 注意:一个槽有三种状态 1.从未被使用过,HashMap.UNUSED。此槽没有被使用和冲突过,查找时只要找到UNUSED就不用再继续探查了 2.使用过但是remove了,此时是HashMap.EMPTY,该谈差点后面的元素仍可能是有key 3.槽正在使用Slot节点 """ def__init__(self,key,value): self.key=key self.value=value classHashTable(object): UNUSED=None#表示slot没有被使用过 EMPTY=Slot(None,None)#使用过被删除 def__init__(self): self._table=Array(8,init=HashTable.UNUSED)#初始化,数组的每个元素都是UNUSED self.length=0 @property#内置装饰器,把方法变成属性 def_load_factor(self): returnself.length/float(len(self._table)) def__len__(self): returnself.length def_hash(self,key): returnabs(hash(key))%len(self._table)#abs函数返回绝对值hash是内置函数_hash直接使用内置的哈希函数,对数组的长度取模 def_find_key(self,key): index=self._hash(key)#先用_hash方法计算出槽的位置 _len=len(self._table)#现保存下来长度 whileself._table[index]isnotHashTable.UNUSED:#如果这个槽不是没有被使用过 ifself._table[index]isHashTable.EMPTY:#如果这个槽是,曾经有过值,不过被删除了 index=(index*5+1)%_len#cpython使用的一种解决哈希冲突的方式 continue elifself._table[index].key==key:#正在使用,如果key值相同 returnindex else:#这里就只剩最后一种可能,正在使用,但是key没有找到 index=(index*5+1)%_len returnNone def_slot_can_insert(self,index):#判断一个槽是否可以插入 return(self._table[index]isHashTable.EMPTYorself._table[index]isHashTable.UNUSED) def_find_slot_for_insert(self,key):#寻找一个空槽,用来插入 index=self._hash(key) _len=len(self._table) whilenotself._slot_can_insert(index): index=(index*5+1)%_len returnindex def__contains__(self,key):#实现一个in操作符 index=self._find_key(key) returnindexisnotNone defadd(self,key,value): ifkeyinself:#上面实现的in操作符 index=self._find_key(key) self._table[index].value=value returnFalse#返回False表示没有执行插入操作,执行的是更新操作 else: index=self._find_slot_for_insert(key) self._table[index]=Slot(key,value)#这两部可能会调用_slot_can_insert函数,不管是哪种情况,EMPTY或是UNUSEZD,都将这个节点声明为Slot类 self.length+=1 ifself._load_factor>=0.8: self._rehash()#当空间占用大于0.8的时候,进行rehash重新分配空间。 returnTrue def_rehash(self): old_table=self._table newsize=len(self._table)*2 self._table=Array(newsize,HashTable.UNUSED) self.length=0 forslotinold_table: ifslotisnotHashTable.UNUSEDandslotisnotHashTable.EMPTY:#判断这个slot是有值的 index=self._find_slot_for_insert(slot.key)#找到一个可以插入的槽 self._table[index]=slot self.length+=1 defget(self,key,default=None): index=self._find_key(key) ifindexisNone: returndefault else: returnself._table[index].value defremove(self,key): index=self._find_key(key) ifindexisNone: raiseKeyError() value=self._table[index].value self.length-=1 self._table[index]=HashTable.EMPTY returnvalue def__iter__(self):#遍历操作,python字典默认遍历的是key,这里实现的也是遍历key forslotinself._table: ifslotnotin(HashTable.EMPTY,HashTable.UNUSED): yieldslot.key classDictADT(HashTable): def__setitem__(self,key,value):#设定给定键的值 self.add(key,value) def__getitem__(self,key):#返回给定键的值 ifkeynotinself: raiseKeyError() else: returnself.get(key) def_iter_slot(self): forslotinself._table: ifslotnotin(HashTable.EMPTY,HashTable.UNUSED): yieldslot defitems(self): forslotinself._iter_slot(): yield(slot.key,slot.value) defkeys(self): forslotinself._iter_slot(): yieldslot.key defvalues(self): forslotinself._iter_slot(): yieldslot.value deftest_dict(): importrandom d=DictADT() d['a']=1#这时候调用__setitem__方法 assertd['a']==1 d.remove('a') l=list(range(30)) random.suffle(l)#打乱l foriinl: d.add(i,i) foriinrange(30): assertd.get(i)==i assertsorted(list(d.keys()))==sorted(l)
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。