麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 學院 > 開發設計 > 正文

Python數據結構——散列表

2019-11-14 17:44:32
字體:
來源:轉載
供稿:網友

散列表的實現常常叫做散列(hashing)。散列僅支持INSERT,SEARCH和DELETE操作,都是在常數平均時間執行的。需要元素間任何排序信息的操作將不會得到有效的支持。

散列表是普通數組概念的推廣。如果空間允許,可以提供一個數組,為每個可能的關鍵字保留一個位置,就可以運用直接尋址技術。

當實際存儲的關鍵字比可能的關鍵字總數較小時,采用散列表就比較直接尋址更為有效。在散列表中,不是直接把關鍵字用作數組下標,而是根據關鍵字計算出下標,這種

關鍵字與下標之間的映射就叫做散列函數。

1.散列函數

一個好的散列函數應滿足簡單移植散列的假設:每個關鍵字都等可能的散列到m個槽位的任何一個中去,并與其它的關鍵字已被散列到哪個槽位無關。

1.1 通常散列表的關鍵字都是自然數。

1.11 除法散列法

通過關鍵字k除以槽位m的余數來映射到某個槽位中。

hash(k)=k mod m

應用除法散列時,應注意m的選擇,m不應該是2的冪,通常選擇與2的冪不太接近的質數。

1.12 乘法散列法

乘法方法包含兩個步驟,第一步用關鍵字k乘上常數A(0<A<1),并取出小數部分,然后用m乘以這個值,再取結果的底(floor)。

hash(k)=floor(m(kA mod 1))

乘法的一個優點是對m的選擇沒有什么特別的要求,一般選擇它為2的某個冪。

一般取A=(√5-1)/2=0.618比較理想。

1.13 全域散列

隨機的選擇散列函數,使之獨立于要存儲的關鍵字。在執行開始時,就從一族仔細設計的函數中,隨機的選擇一個作為散列函數,隨機化保證了

沒有哪一種輸入會始終導致最壞情況發生。

1.2 如果關鍵字是字符串,散列函數需要仔細的選擇

1.2.1 將字符串中字符的ASCII碼值相加

def _hash(key,m):    hashVal=0    for _ in key:        hashVal+=ord(_)    return hashVal%m

由于ascii碼最大127,當表很大時,函數不會很好的分配關鍵字。

1.2.2 取關鍵字的前三個字符。

值27表示英文字母表的字母個數加上一個空格。

hash(k)=k[0]+27*k[1]+729*k[2]

1.2.3 用霍納法則把所有字符擴展到n次多項式。

用32代替27,可以用于位運算。

def _hash(key,m):    hashval=0    for _ in key:        hashval=(hashval<<5)+ord(_)    return hashval%m

2. 分離鏈接法

散列表會面臨一個問題,當兩個關鍵字散列到同一個值的時候,稱之為沖突或者碰撞(collision)。解決沖突的第一種方法通常叫做分離鏈接法(separate chaining)。

其做法是將散列到同一個值的所有元素保留到一個鏈表中,槽中保留一個指向鏈表頭的指針。

為執行FIND,使用散列函數來確定要考察哪個表,遍歷該表并返回關鍵字所在的位置。

為執行INSERT,首先確定該元素是否在表中。如果是新元素,插入表的前端或末尾。

為執行DELETE,找到該元素執行鏈表刪除即可。

散列表中元素個數與散列表大小的比值稱之為裝填因子(load factor)λ。

執行一次不成功的查找,遍歷的鏈接數平均為λ,成功的查找則花費1+(λ/2)。

分離鏈接散列的一般做法是使得λ盡量接近于1。

代碼:

class _ListNode(object):    def __init__(self,key):        self.key=key        self.next=Noneclass HashMap(object):    def __init__(self,tableSize):        self._table=[None]*tableSize        self._n=0  #number of nodes in the map    def __len__(self):        return self._n    def _hash(self,key):        return abs(hash(key))%len(self._table)    def __getitem__(self,key):        j=self._hash(key)        node=self._table[j]        while node is not None and node.key!=key :            node=node.next        if node is None:            raise KeyError,'KeyError'+rePR(key)        return node            def insert(self,key):        try:            self[key]        except KeyError:            j=self._hash(key)            node=self._table[j]            self._table[j]=_ListNode(key)            self._table[j].next=node            self._n+=1    def __delitem__(self,key):        j=self._hash(key)        node=self._table[j]        if node is not None:            if node.key==key:                self._table[j]=node.next                self._-=1            else:                while node.next!=None:                    pre=node                    node=node.next                    if node.key==key:                        pre.next=node.next                        self._n-=1                        break

3.開放定址法

 在開放定址散列算法中,如果有沖突發生,那么就要嘗試選擇另外的單元,直到找出空的單元為止。

   h(k,i)=(h'(k)+f(i)) mod m,i=0,1,...,m-1   ,其中f(0)=0

3.1 線性探測法

函數f(i)是i的線性函數

  h(k,i)=(h'(k)+i) mod m 

相當于逐個探測每個單元

線性探測會存在一個問題,稱之為一次群集。隨著被占用槽的增加,平均查找時間也會不斷增加。當一個空槽前有i個滿的槽時,該空槽為下一個將被占用

槽的概率是(i+1)/m。連續被占用槽的序列會越來越長,平均查找時間也會隨之增加。

如果表有一半多被填滿的話,線性探測不是個好辦法。

3.2 平法探測

 平方探測可以取消線性探測中的一次群集問題。

h(k,i)=(h'(k)+c1i+c2i2) mod m

平方探測中,如果表的一半為空,并且表的大小是質數,保證能夠插入一個新的元素。

平方探測會引起二次群集的問題。

3.3 雙散列

雙散列是用于開放定址法的最好方法之一。

h(k,i)=(h1(k)+ih2(k)) mod m

為能查找整個散列表,值h2(k)要與m互質。確保這個條件成立的一種方法是取m為2的冪,并設計一個總產生奇數的h2。另一種方法是取m為質數,并設計一個總是產生

較m小的正整數的h2。

例如取:

h1(k)=k mod m,h2(k)=1+(k mod m'),m'為略小于m的整數。

給定一個裝填因子λ的開放定址散列表,插入一個元素至多需要1/(1-λ)次探查。

給定一個裝填因子λ<1的開放定址散列表,一次成功查找中的期望探查數至多為(1/λ)ln(1/1-λ)。

4.  再散列

如果表的元素填得太滿,那么操作的運行時間將開始消耗過長。一種解決方法是當表到達某個裝填因子時,建立一個大約兩倍大的表,而且使用一個相關的新散列函數,

掃描整個原始散列表,計算每個元素的新散列值并將其插入到新表中。

 為避免開放定址散列查找錯誤,刪除操作要采用懶惰刪除。

代碼

class HashEntry(object):    def __init__(self,key,value):        self.key=key        self.value=valueclass HashTable(object):    _DELETED=HashEntry(None,None)  #用于刪除    def __init__(self,tablesize):        self._table=tablesize*[None]        self._n=0    def __len__(self):        return self._n    def __getitem__(self,key):        found,j=self._findSlot(key)        if not found:            raise KeyError        return self._table[j].value    def __setitem__(self,key,value):        found,j=self._findSlot(key)        if not found:            self._table[j]=HashEntry(key,value)            self._n+=1            if self._n>len(self._table)//2:                self._rehash()        else:            self._table[j].value=value    def __delitem__(self,key):        found,j=self._findSlot(key)        if found:            self._table[j]=HashTable._DELETED   # 懶惰刪除    def _rehash(self):        oldList=self._table        newsize=2*len(self._table)+1        self._table=newsize*[None]        self._n=0        for entry in oldList:            if entry is not None and entry is not HashTable._DELETED:                self[entry.key]=entry.value                self._n+=1                def _findSlot(self,key):        slot=self._hash1(key)        step=self._hash2(key)        firstSlot=None        while True:            if self._table[slot] is None:                if firstSlot is None:                    firstSlot=slot                return (False,firstSlot)            elif self._table[slot] is HashTable._DELETED:                firstSlot=slot            elif self._table[slot].key==key:                return (True,slot)            slot=(slot+step)%len(self._table)    def _hash1(self,key):        return abs(hash(key))%len(self._table)    def _hash2(self,key):        return 1+abs(hash(key))%(len(self._table)-2)

  


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 黄污网站在线观看 | 免费高潮在线国 | 免费看黄色一级大片 | 成人精品免费在线观看 | 国语自产免费精品视频在 | 99日韩精品视频 | 成人免费毛片在线观看 | 久久久久久久久久亚洲精品 | 日韩欧美电影在线观看 | 可以免费看av | 欧美激情精品久久久久 | 欧美a∨亚洲欧美亚洲 | 玖玖视频精品 | 深夜福利视频免费观看 | 一级免费看片 | 免费在线观看中文字幕 | 成熟女人特级毛片www免费 | 海角在线观看91一区二区 | 欧美性生交xxxxx免费观看 | 毛片视频网址 | 国产va在线观看 | 久久久久久久免费看 | 久久国产精品小视频 | xxxxhd73国产 | 草操视频 | 一区二区三级视频 | 国色天香综合网 | 亚洲成人在线免费 | 中文字幕欧美专区 | 国产一区二区视频精品 | 午夜久久久精品一区二区三区 | 99视频观看 | 一区二区三区四区视频在线观看 | 国产99久久精品一区二区 | 国产精品久久久久久婷婷天堂 | 亚洲一区二区中文字幕在线观看 | 午夜精品成人一区二区 | 色综合欧美 | 一级性生活视频 | 精品国产一级毛片 | 一级爱片|