亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

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

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)

  


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲精品美女在线观看播放| 69精品小视频| 久久久久久91香蕉国产| 欧洲成人在线视频| 亚洲精品久久7777777| 68精品久久久久久欧美| 亚洲一区亚洲二区亚洲三区| 亚洲欧美国产一区二区三区| 亚洲在线免费视频| 亚洲精品在线视频| 欧美电影免费观看电视剧大全| 久久这里有精品| 深夜成人在线观看| 成人羞羞国产免费| 日韩在线免费av| 欧美裸体视频网站| 久久国产天堂福利天堂| 热门国产精品亚洲第一区在线| 亚洲成人a级网| 久久天天躁狠狠躁夜夜躁| 亚洲91精品在线观看| 久久久久国产精品一区| 精品亚洲精品福利线在观看| 亚洲三级免费看| 国产欧美日韩高清| 岛国av在线不卡| 欧美中文字幕视频在线观看| 国产91精品不卡视频| 性欧美办公室18xxxxhd| 欧美极品xxxx| 国产亚洲精品久久久优势| 日韩在线免费视频观看| 北条麻妃一区二区三区中文字幕| 欧美激情二区三区| 亚洲午夜精品视频| 欧美日韩国产精品专区| 九九热99久久久国产盗摄| 国外成人在线播放| 欧美日韩国产精品一区二区三区四区| 91sao在线观看国产| 久久成年人免费电影| 国产欧美日韩中文字幕在线| 成人欧美一区二区三区在线湿哒哒| 国内外成人免费激情在线视频| 亚洲精品自拍偷拍| 超碰97人人做人人爱少妇| 亚洲美女av在线| 亚洲国内精品视频| 日韩黄色在线免费观看| 亚洲精品国产综合区久久久久久久| 欧美激情va永久在线播放| 欧美午夜视频在线观看| 色悠久久久久综合先锋影音下载| 丁香五六月婷婷久久激情| 国产精品免费一区| 日本久久久久亚洲中字幕| 国产午夜精品视频免费不卡69堂| 国产一区二区丝袜| 亚洲黄色成人网| 91香蕉国产在线观看| 欧美日韩精品中文字幕| 欧美贵妇videos办公室| 国产精品久久久久国产a级| 丝袜美腿亚洲一区二区| 免费成人高清视频| 国产精品爱啪在线线免费观看| 尤物yw午夜国产精品视频明星| 国产999在线观看| 国产三级精品网站| 国产精品www网站| 欧美久久久精品| 亚洲永久免费观看| 色先锋资源久久综合5566| 国产一区深夜福利| 亚洲精选在线观看| 亚洲成人激情小说| 欧美在线一区二区三区四| 国产成人综合精品| 亚洲综合日韩中文字幕v在线| 2021国产精品视频| 欧美国产日韩一区二区三区| 激情亚洲一区二区三区四区| 色一情一乱一区二区| 日韩h在线观看| 国产精品精品视频| 欧美激情aaaa| 在线视频日本亚洲性| 福利精品视频在线| 狠狠躁夜夜躁人人躁婷婷91| 国产视频在线一区二区| 久久91亚洲人成电影网站| 91免费看国产| 久久伊人色综合| 国产成人精品视频在线观看| 亚洲精品免费一区二区三区| 亚洲精品永久免费精品| 日韩美女免费线视频| 精品久久久久久亚洲精品| 日韩在线欧美在线国产在线| 欧美电影第一页| 国产精品国语对白| 不卡毛片在线看| 亚洲乱码一区二区| 日韩欧美精品在线观看| 国产精品久久综合av爱欲tv| 高清欧美性猛交xxxx黑人猛交| 久久久国产视频91| 欧美日本精品在线| 美女精品久久久| 日韩电影免费观看在线观看| 狠狠躁天天躁日日躁欧美| 亚洲欧洲免费视频| 亚洲欧美一区二区三区情侣bbw| 在线播放日韩欧美| 欧洲亚洲在线视频| 亚洲国产高清自拍| 精品亚洲国产成av人片传媒| 欧美午夜久久久| 国产日韩在线看片| 午夜精品久久久久久久久久久久久| 免费成人高清视频| 亚洲日韩欧美视频一区| 国产69精品99久久久久久宅男| 亚洲精品一区中文字幕乱码| 黄色91在线观看| 国产精品∨欧美精品v日韩精品| 欧美日韩999| 精品偷拍一区二区三区在线看| 欧美在线视频免费| 日韩高清电影免费观看完整版| 国产欧美日韩中文字幕在线| 欧美视频在线观看 亚洲欧| 色与欲影视天天看综合网| 国产精品a久久久久久| 久久综合久中文字幕青草| 亚洲电影免费在线观看| 亚洲国产私拍精品国模在线观看| 亚洲欧洲第一视频| 国产美女精品视频免费观看| 亚洲欧美日韩综合| 久久精品国产视频| 日韩av一区在线观看| 精品久久久久久久久久久久| 中文字幕在线观看亚洲| 欧美电影在线免费观看网站| 色哟哟网站入口亚洲精品| 久久精品99无色码中文字幕| 国内精品模特av私拍在线观看| 国产视频一区在线| 亚洲色图50p| 色诱女教师一区二区三区| 91麻豆国产精品| 91九色视频导航| 久久久久久久一| 亚洲影院在线看| 欧美成人免费大片| 一区二区欧美久久| 成人欧美一区二区三区在线湿哒哒| 欧美极品少妇xxxxⅹ裸体艺术| 欧美在线观看日本一区| 在线亚洲国产精品网| 亚洲国产精品字幕| 日韩欧美一区二区在线| 国产成人在线精品|