<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          哈希表哪家強(qiáng)?幾大編程語言吵起來了!

          共 3342字,需瀏覽 7分鐘

           ·

          2020-09-10 04:29

          ??Python貓” ,一個(gè)值得加星標(biāo)的公眾號(hào)

          劇照 | 《少年派的奇幻漂流》

          哈希表華山論劍

          比特宇宙編程語言聯(lián)合委員會(huì)準(zhǔn)備舉辦一次大會(huì),主題為哈希表,給各大編程語言帝國都發(fā)去了邀請(qǐng)函。

          很快就到了大會(huì)這一天

          聯(lián)合委員會(huì)秘書長開場(chǎng)發(fā)言:“諸位,為促進(jìn)技術(shù)交流與發(fā)展,增強(qiáng)各帝國友誼,聯(lián)合委員會(huì)特設(shè)此盛會(huì),感謝諸位的捧場(chǎng)”

          會(huì)場(chǎng)傳來一陣鼓掌聲······

          秘書長繼續(xù)發(fā)言:“本次大會(huì)的主題是哈希表,人類程序員使用最多的數(shù)據(jù)容器之一,各大編程語言帝國相信都有實(shí)現(xiàn)。今天的大會(huì)就圍繞哈希表分為幾個(gè)議題討論,首先是第一個(gè)議題:存儲(chǔ)結(jié)構(gòu)與沖突解決

          存儲(chǔ)結(jié)構(gòu)與沖突解決

          來自GoLang帝國的map率先發(fā)言:“哈希表,哈希表,首先得是個(gè)表嘛,所以最基本的要用一個(gè)數(shù)組來存儲(chǔ),數(shù)組中的每一個(gè)元素叫做bucket。至于hash沖突嘛,就用鏈表來解決嘛”

          GoLang帝國的map說完,有人站了起來:“英雄所見略同!在下C++帝國的unordered_map,我們基本上也是選擇的這種方法”

          此時(shí),Python帝國的代表提出了質(zhì)疑:“鏈表確實(shí)可以解決沖突,不過嘛,這要是沖突太多,鏈表太長,搜尋起來豈不費(fèi)時(shí)?”

          GoLang帝國的map和C++帝國的unordered_map面面相覷,不知如何應(yīng)對(duì)。

          “鏈表太長的話,那就轉(zhuǎn)成樹結(jié)構(gòu)!”,就在這時(shí),又有人站了起來。

          見有人起身,Python帝國代表轉(zhuǎn)身問道:“在下乃Python帝國的字典dict{},敢問閣下怎么稱呼”

          “我是Java帝國的HashMap,和前面兩位兄臺(tái)的策略大體相同,只是在沖突過多,具體來說鏈表長度超過8的時(shí)候就轉(zhuǎn)換成紅黑樹的結(jié)構(gòu),以此加快查找”

          說完,map、unordered_map松了一口氣,和HashMap一起坐下了。

          dict{}繼續(xù)發(fā)問:“在座的都是這個(gè)思路,用鏈表解決沖突?”

          說完,另外一位代表站了起來,“等等,我們C#帝國的HashTable就沒用鏈表!”

          dict{}露出了滿意的表情,“那你們是怎么解決沖突的呢?”

          “咱HashTable內(nèi)部使用的是雙重散列法,咱內(nèi)部不止一種哈希計(jì)算方式,一次Hash沖突,咱就換一個(gè)再算,直到找到有空位的地方存儲(chǔ)”,HashTable回答到。

          dict{}看起來有些失望,估計(jì)這也不是他所用的方式。

          “你問了半天,還沒說你們Python是怎么處理沖突的呢?”,Java帝國的HashMap開口了。

          “是啊,是啊”,其他代表也跟著起哄。

          見眾人起哄,dict{}只好應(yīng)答:“鏈表法固然不錯(cuò),不過需要在插入數(shù)據(jù)過程中動(dòng)態(tài)分配內(nèi)存構(gòu)建鏈表節(jié)點(diǎn),開銷不小,我們沒有采用。”

          “那到底用了啥,你倒是說啊,快急死我了”,C++的unordered_map有些急了。

          “我們用的是一種叫開放尋址法的策略,如果發(fā)現(xiàn)了沖突,就按照制定的策略從這個(gè)位置往后找,直到找到有空的位置存儲(chǔ)”,dict{}繼續(xù)說到。

          “哪有那么簡單的事,你把別人的位置占了,那對(duì)應(yīng)那個(gè)位置的數(shù)據(jù)來了怎么辦?還有查找怎么找?刪除怎么處理?這不全亂套了嗎”,unordered_map追問不舍。

          “是這樣的,按照我們既定的規(guī)則,在查找的時(shí)候就需要額外做一些工作,另外刪除的時(shí)候也不能直接刪除,否則會(huì)破壞規(guī)則鏈條·····”,接下來一段時(shí)間,dict{}給大家仔細(xì)介紹了他們的處理思路。

          “你這個(gè)也太麻煩了,不如我們鏈表法來的清晰明了”

          “這怎么就麻煩了?這好處不顯而易見嘛?”,dict{}也不甘示弱。

          這時(shí),秘書長打斷了大家的爭(zhēng)辯:“諸位,諸位,靜一靜,靜一靜,咱們這個(gè)議題到此為止,進(jìn)入下一個(gè)議題:哈希到位置映射

          哈希到位置映射

          急性子的C++帝國代表unordered_map第一個(gè)說話:“這有什么好討論的,不就是用hash值對(duì)哈希表數(shù)組長度進(jìn)行一個(gè)求模運(yùn)算嗎?”

          “就是,這有什么好討論的”,C#帝國的HashTable也附和到。

          “哎,此言差矣,我就沒用取模運(yùn)算”,眾人望去,這Python帝國的dict{}又要鬧什么新鮮玩意。

          GoLang帝國的map問道:“老哥用的什么辦法,別賣關(guān)子了,快說來聽聽”

          dict{}掃了眾人一眼說到,“我的辦法就是:”

          這是怎么個(gè)映射法?眾代表皆摸不著頭腦,議論紛紛,唯有Java帝國的HashMap聽聞微微一笑。

          dict{}見狀問道:“HashMap兄臺(tái),莫非知曉其中玄機(jī)?”

          只見HashMap不緊不慢的站了起來說到:“哈希表長度是2的冪次,減1之后的二進(jìn)制均變成了1,比如長度16,減1變成15,也就是二進(jìn)制1111。再進(jìn)行與運(yùn)算,相當(dāng)于取了哈希值的低位,直接映射到對(duì)應(yīng)的數(shù)組位置,與運(yùn)算比取模運(yùn)算要快不少。不瞞諸位,我HashMap中也是使用的這種方式,此乃雕蟲小技,不值得炫耀”

          眾代表聽完紛紛點(diǎn)頭稱贊,dict{}不知何時(shí)卻已坐下。

          C#的HashTable問道:“這樣直接取低幾位,會(huì)不會(huì)造成Hash值到數(shù)組到映射不均勻,拿你舉的例子來說,18的二進(jìn)制是0001 0010,34的二進(jìn)制是0010 0010,他們的低4位都一樣,和1111與上以后都是0010,也就是都該存到數(shù)組的2號(hào)位,這豈不是一定程度上的增加了沖突的概率嗎?”

          突如其來的質(zhì)疑并沒有讓HashMap慌亂,反而是從容不迫的解釋到:“C#代表的這個(gè)問題提的非常好,不知dict{}兄臺(tái)是如何處理的。我們的方案是在進(jìn)行與運(yùn)算映射之前,對(duì)hash值進(jìn)行一個(gè)處理,具體來說就是將其高16位與低16位進(jìn)行一個(gè)異或運(yùn)算,如此一來,最終參與與運(yùn)算的部分就融合了原始hash的全部信息,而不僅僅是低位。”

          眾代表聽完再次點(diǎn)頭稱贊。

          秘書長打破了平靜,“看來大家收獲都頗豐,咱們接著下一個(gè)話題吧:初始容量與擴(kuò)容

          初始容量與擴(kuò)容

          眾代表這一次皆不爭(zhēng)先,互相觀望。

          秘書長見狀說到:“沒人主動(dòng),那我可就要點(diǎn)名了······”

          “那就我先吧”,Java帝國的HashMap站了起來,“我的默認(rèn)初始容量是16,有一個(gè)叫負(fù)載因子的參數(shù),默認(rèn)是0.75。我的策略是,如果內(nèi)部數(shù)組的空間使用了超過75%,那就要準(zhǔn)備擴(kuò)容了,否則后續(xù)Hash沖突的概率就會(huì)很大。哦對(duì)了,擴(kuò)容時(shí)容量得是2的指數(shù)次方,原因前面已經(jīng)交代了”

          dict{}第二個(gè)起身:“嗯,差不多,我的默認(rèn)初始容量是8,擴(kuò)容的時(shí)候也是要求是2的指數(shù)次方,另外我的負(fù)載因子是2/3,擴(kuò)容時(shí)機(jī)比這位HashMap老哥更早一些”

          C#帝國代表HashTable聽聞也起身發(fā)言:“我的初始容量是3,至于負(fù)載因子嘛,我經(jīng)過大量實(shí)驗(yàn)測(cè)試,得出的數(shù)據(jù)在兩位之間,是0.72。容量大小方面我就沒有2的指數(shù)次方的要求了,而是要求一個(gè)素?cái)?shù)。之所以要求素?cái)?shù)的原因,是因?yàn)槲沂褂玫那竽_\(yùn)算進(jìn)行的映射,使用素?cái)?shù)的話,沖突會(huì)少一些。”

          這時(shí),C++帝國代表unordered_map也說話了,“巧了!我也是素?cái)?shù)哎,你看,我提前把容量都算好存起來了,到時(shí)候擴(kuò)容就挨個(gè)取就行了。”

          尾聲

          時(shí)間過的很快,在大家熱情的討論中,一上午時(shí)間很快就結(jié)束了。

          大會(huì)臨近尾聲,秘書長致辭宣布:“感謝各位代表積極探討,大會(huì)取得圓滿成功,本次大會(huì)到此結(jié)束,咱們下次再會(huì)!”

          會(huì)場(chǎng)再次傳來一陣熱烈的鼓掌聲······

          然而就在此時(shí),會(huì)場(chǎng)外突然傳來一個(gè)聲音:“舉辦如此盛會(huì),怎能少了我”

          眾人望去,皆嘆:“他果然還是來了”

          彩蛋

          會(huì)后,C#帝國代表拉住了C++帝國代表

          “兄弟,八卦一下,你這取的是個(gè)啥名,你看我和Java帝國的代表都叫Hashxxx,你咋不也叫hash_map或者hash_table之類的名字呢?叫什么unordered_map

          “哎,兄臺(tái)你有所不知,其實(shí)我也不想叫這名字,只是,,,這話說來話長了······”,unordered_map嘆了口氣。



          優(yōu)質(zhì)文章,推薦閱讀:

          Python 中的數(shù)字到底是什么?

          一篇文章掌握 Python 內(nèi)置 zip() 的全部內(nèi)容

          Python 為什么使用縮進(jìn)來劃分代碼塊?

          Python 協(xié)程與 Go 協(xié)程的區(qū)別(二)

          感謝創(chuàng)作者的好文
          瀏覽 33
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  无码中文字 | 五月天狠狠操 | 欧美一区二区丁香五月天激情 | 日韩黄色电影在线免费观看 | 成人91无码在线18 |