国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Java學(xué)數(shù)據(jù)結(jié)構(gòu)(4)——散列表Hash table & 散列函數(shù) & 哈希沖突

這篇具有很好參考價值的文章主要介紹了Java學(xué)數(shù)據(jù)結(jié)構(gòu)(4)——散列表Hash table & 散列函數(shù) & 哈希沖突。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

引出


1.散列表,key,散列函數(shù);
2.哈希沖突的解決;
3.string中的hashCode;文章來源地址http://www.zghlxwxcb.cn/news/detail-686415.html

Java學(xué)數(shù)據(jù)結(jié)構(gòu)(4)——散列表Hash table & 散列函數(shù) & 哈希沖突,Java,哈希算法,數(shù)據(jù)結(jié)構(gòu),java

散列表Hash table

查找樹ADT,它允許對元素的集合進行各種操作。本章討論散列表(hash table)ADT,不過它只支持二叉查找樹所允許的一部分操作。散列表的實現(xiàn)常常叫作散列(hashing)。散列是一種用于以常數(shù)平均時間執(zhí)行插入、刪除和查找的技術(shù)。但是,那些需要元素間任何排序信息的樹操作將不會得到有效的支持。因此,諸如findMin、findMax以及以線性時間將排過序的整個表進行打印的操作都是散列所不支持的。

  • 看到實現(xiàn)散列表的幾種方法。
  • 解析地比較這些方法。
  • 介紹散列的多種應(yīng)用。
  • 將散列表和二叉查找樹進行比較。

關(guān)鍵字Key和散列函數(shù)(hash function)

理想的散列表數(shù)據(jù)結(jié)構(gòu)只不過是一個包含一些項(itm)的具有固定大小的數(shù)組。通常查找是對項的某個部分(即數(shù)據(jù)域)進行的。這部分就叫作關(guān)鍵字(key)。

例如,項可以由一個字符串(它可以作為關(guān)鍵字)和其他一些數(shù)據(jù)域組成(例如,姓名是大型雇員結(jié)構(gòu)的一部分)。我們把表的大小記作TableSize,并將其理解為散列數(shù)據(jù)結(jié)構(gòu)的一部分,而不僅僅是浮動于全局的某個變量。通常的習(xí)慣是讓表從0到TableSize-1變化;稍后我們就會明白為什么要這樣做。

每個關(guān)鍵字被映射到從0到TableSize-1這個范圍中的某個數(shù),并且被放到適當(dāng)?shù)膯卧?/strong>。這個映射就叫作散列函數(shù)(hash function),理想情況下它應(yīng)該計算起來簡單,并且應(yīng)該保證任何兩個不同的關(guān)鍵字映射到不同的單元。不過,這是不可能的,因為單元的數(shù)目是有限的,而關(guān)鍵字實際上是用不完的。因此,我們尋找一個散列函數(shù),該函數(shù)要在單元之間均勻地分配關(guān)鍵字。

圖5-1是完美情況的一個典型。在這個例子中,john散列到3,phil散列到4,dave散列到6,mary散列到7。

Java學(xué)數(shù)據(jù)結(jié)構(gòu)(4)——散列表Hash table & 散列函數(shù) & 哈希沖突,Java,哈希算法,數(shù)據(jù)結(jié)構(gòu),java

這就是散列的基本想法。剩下的問題就是要選擇一個函數(shù),決定當(dāng)兩個關(guān)鍵字散列到同一個值的時候(這叫作沖突(collision))應(yīng)該做什么以及如何確定散列表的大小。

散列函數(shù)

Java學(xué)數(shù)據(jù)結(jié)構(gòu)(4)——散列表Hash table & 散列函數(shù) & 哈希沖突,Java,哈希算法,數(shù)據(jù)結(jié)構(gòu),java

這個散列函數(shù)利用到事實:允許溢出。這可能會引進負的數(shù),因此在末尾有附加的測試。圖5-4所描述的散列函數(shù)就表的分布而言未必是最好的,但確實具有極其簡單的優(yōu)點而且速度也很快。如果關(guān)鍵字特別長,那么該散列函數(shù)計算起來將會花費過多的時間。在這種情況下通常的經(jīng)驗是不使用所有的字符。此時關(guān)鍵字的長度和性質(zhì)將影響選擇。例如,關(guān)鍵字可能是完整的街道地址,散列函數(shù)可以包括街道地址的幾個字符,也許還有城市名和郵政編碼的幾個字符。有些程序設(shè)計人員通過只使用奇數(shù)位置上的字符來實現(xiàn)他們的散列函數(shù),這里有這么一層想法:用計算散列函數(shù)節(jié)省下的時間來補償由此產(chǎn)生的對均勻地分布的函數(shù)的輕微干擾。

Java學(xué)數(shù)據(jù)結(jié)構(gòu)(4)——散列表Hash table & 散列函數(shù) & 哈希沖突,Java,哈希算法,數(shù)據(jù)結(jié)構(gòu),java

解決collision哈希沖突(碰撞)

剩下的主要編程細節(jié)是解決沖突的消除問題。如果當(dāng)一個元素被插入時與一個已經(jīng)插入的元素散列到相同的值,那么就產(chǎn)生一個沖突,這個沖突需要消除。解決這種沖突的方法有幾種,我們將討論其中最簡單的兩種:分離鏈接法和開放定址法。

分離鏈接法(separate chaining)

分離鏈接法(separate chaining)

解決沖突的第一種方法通常叫作分離鏈接法(separate chaining),其做法是將散列到同一個值的所有元素保留到一個表中。我們可以使用標準庫表的實現(xiàn)方法。如果空間很緊,則更可取的方法是避免使用它們(因為這些表是雙向鏈接的并且浪費空間)。本節(jié)我們假設(shè)關(guān)鍵字是前10個完全平方數(shù)并設(shè)散列函數(shù)就是hash(x)=xmod10(表的大小不是素數(shù),用在這里是為了簡單)。

Java學(xué)數(shù)據(jù)結(jié)構(gòu)(4)——散列表Hash table & 散列函數(shù) & 哈希沖突,Java,哈希算法,數(shù)據(jù)結(jié)構(gòu),java

探測散列表(probing hash table)

探測散列表(probing hash table)

Java學(xué)數(shù)據(jù)結(jié)構(gòu)(4)——散列表Hash table & 散列函數(shù) & 哈希沖突,Java,哈希算法,數(shù)據(jù)結(jié)構(gòu),java

分離鏈接散列算法的缺點是使用一些鏈表。由于給新單元分配地址需要時間(特別是在其他語言中),因此這就導(dǎo)致算法的速度有些減慢,同時算法實際上還要求對第二種數(shù)據(jù)結(jié)構(gòu)的實現(xiàn)。另有一種不用鏈表解決沖突的方法是嘗試另外一些單元,直到找出空的單元為止。更常見的是,單元h(x),h,(x),h2(x),…相繼被試選,其中h:(x)=(hash(x)+f(i)mod
TableSize,且f(0)=0。函數(shù)f是沖突解決方法。因為所有的數(shù)據(jù)都要置入表內(nèi),所以這種解決方案所需要的表要比分離鏈接散列的表大。一般說來,對于不使用分離鏈接的散列表來說,其裝填因子應(yīng)該低于入=0.5。我們把這樣的表叫作探測散列表(probing hash table)?,F(xiàn)在我們就來考察三種通常的沖突解決方案。

Java學(xué)數(shù)據(jù)結(jié)構(gòu)(4)——散列表Hash table & 散列函數(shù) & 哈希沖突,Java,哈希算法,數(shù)據(jù)結(jié)構(gòu),java

第一個沖突在插人關(guān)鍵字49時產(chǎn)生;它被放入下一個空閑地址,即地址0,該地址是開放的。關(guān)鍵字58先與18沖突,再與89沖突,然后又和49沖突,試選三次之后才找到一個空單元。對69的沖突用類似的方法處理。只要表足夠大,總能夠找到一個自由單元,但是如此花費的時間是相當(dāng)多的。更糟的是,即使表相對較空,這樣占據(jù)的單元也會開始形成一些區(qū)塊,其結(jié)果稱為一次聚集(primary clustering),就是說,散列到區(qū)塊中的任何關(guān)鍵字都需要多次試選單元才能夠解決沖突,然后該關(guān)鍵字被添加到相應(yīng)的區(qū)塊中。

平方探針

平方探測是消除線性探測中一次聚集問題的沖突解決方法。平方探測就是沖突函數(shù)為二次的探測方法。流行的選擇是f(i)=i**2。圖5-13顯示與前面線性探測例子相同的輸人使用該沖突函數(shù)所得到的散列表。

Java學(xué)數(shù)據(jù)結(jié)構(gòu)(4)——散列表Hash table & 散列函數(shù) & 哈希沖突,Java,哈希算法,數(shù)據(jù)結(jié)構(gòu),java

當(dāng)49與89沖突時,其下一個位置為下一個單元,該單元是空的,因此49就被放在那里。此后,58在位置8處產(chǎn)生沖突,其后相鄰的單元經(jīng)探測得知發(fā)生了另外的沖突。下一個探測的單元在距位置8為2=4遠處,這個單元是個空單元。因此,關(guān)鍵字58就放在單元2處。對于關(guān)鍵字69,處理的過程也一樣。

雖然平方探測排除了一次聚集,但是散列到同一位置上的那些元素將探測相同的備選單元。這叫作二次聚集(secondary clustering)。二次聚集是理論上的一個小缺憾。模擬結(jié)果指出,對每次查找,它一般要引起另外的少于一半的探測。下面的技術(shù)將會排除這個缺撼,不過這要付出計算一個附加的散列函數(shù)的代價。

雙散列(double hashing)

Java學(xué)數(shù)據(jù)結(jié)構(gòu)(4)——散列表Hash table & 散列函數(shù) & 哈希沖突,Java,哈希算法,數(shù)據(jù)結(jié)構(gòu),java

我們將要考察的最后一個沖突解決方法是雙散列(double hashing)。對于雙散列,一種流行的選擇是f(i)=i·hash2(x)。這個公式是說,我們將第二個散列函數(shù)應(yīng)用到x并在距離hash2(x),2hash(x),…等處探測。hash2(x)選擇得不好將會是災(zāi)難性的。例如,若把99插入到前面例子中的輸入中去,則通常的選擇hash2(x)=xmod9將不起作用。因此,函數(shù)一定不要算得0值。另外,保證所有的單元都能被探測到也是很重要的(但在下面的例子中這是不可能的,因為表的大小不是素數(shù))。諸如hash2(x)=R-(x mod R)這樣的函數(shù)將起到良好的作用,其中R為小于TableSize的素數(shù)。如果我們選擇R=7,則圖5-18顯示插入與前面相同的一些關(guān)鍵字的結(jié)果。

第一個沖突發(fā)生在49被插入的時候。hash2(49)=7-0=7,故49被插入到位置6。hash2(58)7-2=5,于是58被插人到位置3。最后,69產(chǎn)生沖突,從而被插入到距離為hash2(69)=7-6=1遠的地方。如果我們試圖將60插入到位置0處,那么就會產(chǎn)生一個沖突。由于hash2(60)=74=3,因此我們嘗試位置3、6、9,然后是2,直到找出一個空的單元。一般是有可能發(fā)現(xiàn)某個壞

Java學(xué)數(shù)據(jù)結(jié)構(gòu)(4)——散列表Hash table & 散列函數(shù) & 哈希沖突,Java,哈希算法,數(shù)據(jù)結(jié)構(gòu),java

Java標準庫中的散列表

標準庫包括Set和Map的散列表的實現(xiàn),即HashSet類和HashMap類。HashSet中的項(或HashSet中的關(guān)鍵字)必須提供equals方法和hashCode方法,如較早我們在節(jié)5.3所描述的那樣。HashSet和HashMap通常是用分離鏈接散列實現(xiàn)的。

如果這些表項是否可以依有序方式查看這一點并不重要,那么這些類可以使用。例如,在4.8節(jié)的單詞變換例子中,存在三種映射:

1.其中關(guān)鍵字為單詞長度(word length),而關(guān)鍵字的值是長為該單詞長度的所有單詞的集合。

2.關(guān)鍵字是一個代表(representative),而關(guān)鍵字的值是具有該代表的所有單詞的集合。

3.關(guān)鍵字是一個單詞(wod),而關(guān)鍵字的值是與該單詞只有一個字母不同的所有單詞的集合。

因為單詞長度被處理的順序并不重要,所以第1個映射可以是HashMap。而由于第2個映射建立以后甚至不需要代表,因此第2個映射也可以是HashMap。第3個映射還可以是HashMap,除非我們想要printHighChangeables依字母順序列出單詞的子集(這些單詞可以被變換成許多其他單詞)。

HashMap的性能常常優(yōu)于TreeMap的性能,不過不按這兩種方式編寫代碼很難有把握肯定。因此,在HashMap或TreeMap可以接受的情況下,更可取的方法是:使用接口類型Map進行變量的聲明,然后,將TreeMap的實例變成HashMap的實例并進行計時測試。

在Java中,能夠被合理地插人到一個HashSet中去或是所謂關(guān)鍵字被插入到HashMap中去的那些庫類型已經(jīng)被定義了equals和hashCode方法。

特別是String類中有一個hashCode方法。

Java學(xué)數(shù)據(jù)結(jié)構(gòu)(4)——散列表Hash table & 散列函數(shù) & 哈希沖突,Java,哈希算法,數(shù)據(jù)結(jié)構(gòu),java


總結(jié)

1.散列表,key,散列函數(shù);
2.哈希沖突的解決;
3.string中的hashCode;

到了這里,關(guān)于Java學(xué)數(shù)據(jù)結(jié)構(gòu)(4)——散列表Hash table & 散列函數(shù) & 哈希沖突的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • 數(shù)據(jù)結(jié)構(gòu)8 散列函數(shù)

    1-1 分數(shù) 1 作者 DS課程組單位 浙江大學(xué) Store M elements in a hash table which is represented by an array of size S , the loading density is then M / S . 將M個元素存儲在哈希表中,哈希表由大小為S的數(shù)組表示,則加載密度為M/S。 T F 1-2 分數(shù) 1 作者 馮雁單位 浙江大學(xué) In hashing, functions \\\"insert\\\" and \\\"find\\\" h

    2024年02月07日
    瀏覽(23)
  • 數(shù)據(jù)結(jié)構(gòu) in Golang:Hash Tables(哈希表)

    水果店的價格表: 蘋果 Apple:3元 香蕉 Banana:4元 桃子 Peach:2元 梨 Pear:3元 找到一種水果的價格: 可以使用 binary search,通過名稱來查找,耗時:O(logn) 如何只耗時 O(1) 來找到價格呢? Hash 函數(shù):通過一個字符串 - 一個數(shù)值 例如: \\\"Apple\\\" - 1 \\\"Banana\\\" - 2 \\\"Peach\\\" - 7 \\\"Pear\\\" - 8 將字符

    2024年02月08日
    瀏覽(23)
  • lua變量、數(shù)據(jù)類型、if判斷條件和數(shù)據(jù)結(jié)構(gòu)table以及【lua 函數(shù)】

    Lua 變量有三種類型: 全局變量 和 局部變量 和 表中的域 。 ? 全局變量:默認情況下,Lua中所有的變量都是全局變量。 ? 局部變量:使用 local 顯式聲明在函數(shù)內(nèi)的變量,以及函數(shù)的參數(shù),都是局部變量。在函數(shù)外即使用 local 去聲明,它的作用域也是當(dāng)前的整個文件,這相

    2023年04月19日
    瀏覽(24)
  • 【數(shù)據(jù)結(jié)構(gòu)】哈希表——閉散列 | 開散列(哈希桶)

    【數(shù)據(jù)結(jié)構(gòu)】哈希表——閉散列 | 開散列(哈希桶)

    ??作者:一只大喵咪1201 ??專欄:《數(shù)據(jù)結(jié)構(gòu)與算法》 ??格言: 你只管努力,剩下的交給時間! 哈希(Hash):是一種方法,將數(shù)據(jù)的key值和存儲位置建立關(guān)系。 在之前學(xué)習(xí)過的順序結(jié)構(gòu)以及平衡樹中,所有數(shù)據(jù)的key值和存儲位置之間都沒有對應(yīng)的關(guān)系。所以在查找一個數(shù)據(jù)

    2023年04月24日
    瀏覽(45)
  • 數(shù)據(jù)結(jié)構(gòu)(順序結(jié)構(gòu)、鏈式結(jié)構(gòu)、索引結(jié)構(gòu)、散列結(jié)構(gòu))

    數(shù)據(jù)結(jié)構(gòu)(順序結(jié)構(gòu)、鏈式結(jié)構(gòu)、索引結(jié)構(gòu)、散列結(jié)構(gòu))

    數(shù)據(jù)結(jié)構(gòu),就是一種程序設(shè)計優(yōu)化的方法論,研究數(shù)據(jù)的邏輯結(jié)構(gòu)和物理結(jié)構(gòu)以及它們之間相互關(guān)系,并對這種結(jié)構(gòu)定義相應(yīng)的運算, 目的是加快程序的執(zhí)行速度、減少內(nèi)存占用的空間 。 數(shù)據(jù)的邏輯結(jié)構(gòu)指反映數(shù)據(jù)元素之間的邏輯關(guān)系,而與數(shù)據(jù)的存儲無關(guān),是獨立于計算

    2024年02月03日
    瀏覽(21)
  • 【數(shù)據(jù)結(jié)構(gòu)】哈希表的開散列和閉散列模擬

    【數(shù)據(jù)結(jié)構(gòu)】哈希表的開散列和閉散列模擬

    在順序和樹狀結(jié)構(gòu)中,元素的存儲與其存儲位置之間是沒有對應(yīng)關(guān)系,因此在查找一個元素時,必須要經(jīng)過多次的比較。 順序查找的時間復(fù)雜度為0(N),樹的查找時間復(fù)雜度為log(N)。 我們最希望的搜索方式:通過元素的特性,不需要對比查找,而是直接找到某個元素。 這一個

    2024年02月22日
    瀏覽(25)
  • 【數(shù)據(jù)結(jié)構(gòu)】3.跳表和散列

    【數(shù)據(jù)結(jié)構(gòu)】3.跳表和散列

    跳表可以近似實現(xiàn)二分查找的效果 以下面長度為7的鏈表舉例,該跳表通過3條鏈表進行存儲。假設(shè)要查找元素80: 首先在第2級鏈表查找,因為80大于40,所以在第3個節(jié)點右側(cè)查找 然后在第1級鏈表查找,因為80大于75,所以在第5個節(jié)點右側(cè)查找 最后在第0級鏈表查找,找到元素

    2024年02月08日
    瀏覽(29)
  • 數(shù)據(jù)結(jié)構(gòu)中處理散列沖突的四種方法

    數(shù)據(jù)結(jié)構(gòu)中處理散列沖突的四種方法

    開放定址法 就是一旦發(fā)生了沖突,就去尋找下一個空的散列地址 只要 散列表 足夠大 空的散列地址總能找到,并將記錄存入 使用該公式用于解決沖突的開放定址法稱為 線性探測法 對于線性探測法,在出現(xiàn)沖突時,它只能晚后一步一步檢測看是否有空位置 假設(shè)此時該沖突位

    2024年02月04日
    瀏覽(27)
  • 【數(shù)據(jù)結(jié)構(gòu)與算法】04 哈希表 / 散列表 (哈希函數(shù)、哈希沖突、鏈地址法、開放地址法、SHA256)

    【數(shù)據(jù)結(jié)構(gòu)與算法】04 哈希表 / 散列表 (哈希函數(shù)、哈希沖突、鏈地址法、開放地址法、SHA256)

    一種很好用,很高效,又一學(xué)就會的數(shù)據(jù)結(jié)構(gòu),你確定不看看? 莫慌,每個概念都很好理解。 哈希表( Hash Table ),也稱為 散列表 ,是一種數(shù)據(jù)結(jié)構(gòu), 用于存儲鍵值對(key-value pairs) 。 鍵值對是一種數(shù)據(jù)結(jié)構(gòu),用于將鍵(key)與對應(yīng)的值(value)相關(guān)聯(lián)。在鍵值對中,鍵

    2024年02月09日
    瀏覽(27)
  • 數(shù)據(jù)結(jié)構(gòu)和算法——哈希查找沖突處理方法(開放地址法-線性探測、平方探測、雙散列探測、再散列,分離鏈接法)

    數(shù)據(jù)結(jié)構(gòu)和算法——哈希查找沖突處理方法(開放地址法-線性探測、平方探測、雙散列探測、再散列,分離鏈接法)

    目錄 開放地址法(Open Addressing) 線性探測(Linear Probing) 散列表查找性能分析 平方探測(Quadratic Probing)? 定理 平方探測法的查找與插入 雙散列探測法(Double Hashing)? 再散列(Rehashing) 分離鏈接法(Separate Chaining) 平均查找次數(shù) 分離鏈接法的散列表實現(xiàn) 常用處理沖突的

    2024年02月08日
    瀏覽(23)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包