日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

ds哈希查找—二次探测再散列_大白话之哈希表和哈希算法

發(fā)布時(shí)間:2023/12/2 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ds哈希查找—二次探测再散列_大白话之哈希表和哈希算法 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

哈希表概念

哈希表(散列表),是基于關(guān)鍵碼值(Key value)而直接進(jìn)行訪問的數(shù)據(jù)結(jié)構(gòu)。也就是說,它通過把關(guān)鍵碼值映射到表中一個(gè)位置來訪問記錄,以加快查找的速度。這個(gè)映射函數(shù)叫做散列函數(shù)(哈希函數(shù)),存放記錄的數(shù)組叫做散列表。

上面所提到的哈希函數(shù)是指:有一個(gè)對(duì)應(yīng)關(guān)系 f ,使得每個(gè)關(guān)鍵字和結(jié)構(gòu)中一個(gè)唯一的存儲(chǔ)位置相對(duì)應(yīng),這樣在查找時(shí),我們不需要像傳統(tǒng)的查找算法那樣進(jìn)行比較,而是根據(jù)這個(gè)對(duì)應(yīng)關(guān)系 f 找到給定值K的像f(K)。

哈希函數(shù)與哈希表

  • 這個(gè)hash函數(shù)并沒有什么統(tǒng)一標(biāo)準(zhǔn),它的核心思想就是就是把任意長(zhǎng)度的輸入(又叫做預(yù)映射pre-image)通過散列算法變換成固定長(zhǎng)度的輸出,該輸出就是散列值。
  • 這種轉(zhuǎn)換是一種壓縮映射,也就是,散列值的空間通常遠(yuǎn)小于輸入的空間,不同的輸入可能會(huì)散列成相同的輸出,所以不可能從散列值來確定唯一的輸入值。簡(jiǎn)單的說就是一種將任意長(zhǎng)度的消息壓縮到某一固定長(zhǎng)度的消息摘要的函數(shù),這個(gè)消息可能是字符、數(shù)組、字符串等等。
  • 再使用哈希表進(jìn)行查詢的時(shí)候,就是再次使用哈希函數(shù)將key轉(zhuǎn)換為對(duì)應(yīng)的數(shù)組下標(biāo),并定位到該空間獲取value,如此一來,就可以充分利用到數(shù)組的定位性能進(jìn)行數(shù)據(jù)定位。
  • 擁有這樣的hash存儲(chǔ)結(jié)構(gòu)的數(shù)據(jù)結(jié)構(gòu)稱為散列表,或者叫哈希表。
  • 哈希表一般基于數(shù)組實(shí)現(xiàn),特定情況下結(jié)合鏈表,但是數(shù)組是哈希表基礎(chǔ)數(shù)據(jù)結(jié)構(gòu)。
為什么要有哈希表呢? 數(shù)組的特點(diǎn)是:尋址容易,插入和刪除困難;而鏈表的特點(diǎn)是:尋址困難,插入和刪除容易。那么我們能不能綜合兩者的特性,做出一種尋址容易,插入刪除也容易的數(shù)據(jù)結(jié)構(gòu)?答案是肯定的,這就是我們要提起的哈希表,哈希表有多種不同的實(shí)現(xiàn)方法,我接下來解釋的是最常用的一種方法

哈希算法

構(gòu)造哈希函數(shù)的方法有很多。首先需要明確什么是“好” 的哈希算法。若對(duì)于關(guān)鍵字集合中的任一個(gè)關(guān)鍵字,經(jīng)哈希函數(shù)映像到地址集合中任何一個(gè)地址的概率是相等的,則稱此類哈希函數(shù)是均勻的(Uniform)哈希函數(shù)。換句話說,就是使關(guān)鍵字經(jīng)過哈希函數(shù)得到一個(gè)“隨機(jī)的地址”,以便使一組關(guān)鍵字的哈希地址均勻分布在整個(gè)地址區(qū)間中,從而減少?zèng)_突。

一個(gè)hash函數(shù)需要滿足
  • 接受一個(gè)單一的參數(shù),這個(gè)參數(shù)可以是任何類型,但是只能是一個(gè)。
  • 返回一個(gè)整型值(一般情況下)。
  • 輸出的哈希地址均勻分布在整個(gè)地址區(qū)間中。
  • 對(duì)于兩個(gè)相同的輸入,輸出必須相同。
  • 對(duì)于兩個(gè)不同的輸入,輸出相同的概率需要做到非常小。
  • hash的計(jì)算不能過于復(fù)雜,時(shí)間復(fù)雜度盡可能地低。
  • 既然自己想不到比較好的hash算法,我們就來看看別人是怎么做的吧,下面是一些常用的hash算法:

    • 直接定址法 取key的線性函數(shù)值作為hash值,value = a * key + b,a,b為常數(shù)。這一類散列碼的特點(diǎn)是:對(duì)輸入為整型數(shù)據(jù)而言,不會(huì)產(chǎn)生下標(biāo)沖突。不產(chǎn)生沖突當(dāng)然是最完美的狀態(tài),但是這種方式要求輸入的key遵循一定的線性規(guī)律。

    例如:有一個(gè)01到07的部門人數(shù)統(tǒng)計(jì)表,其中,部門編號(hào)作為關(guān)鍵字,哈希函數(shù)取關(guān)鍵字自身。如下表所示:

    地址01020304050607部門01020304050607人數(shù)23432465643346

    這樣若要詢問01部門有多少人,則只要查表的第01項(xiàng)即可。由于直接定址所得的地址集合和關(guān)鍵字集合的大小相同。因此,對(duì)于不同的關(guān)鍵字不會(huì)發(fā)生沖突,但是實(shí)際中能使用這種哈希函數(shù)的情況很少。
    • 除留余數(shù)法 除留余數(shù)法:假設(shè)數(shù)組的長(zhǎng)度為l,value = key % l,這一種散列碼實(shí)現(xiàn)簡(jiǎn)單,運(yùn)用比較多,但是如果輸入的元素集合不具有一定的規(guī)律,比較容易產(chǎn)生沖突。數(shù)組的長(zhǎng)度最好是質(zhì)數(shù),被除數(shù)為質(zhì)數(shù)在一定程度上可以緩解數(shù)據(jù)堆積的問題。

    除留余數(shù)法此方法為最常用的構(gòu)造散列函數(shù)方法。對(duì)于散列表長(zhǎng)為m的散列函數(shù)公式為: f( key ) = key mod p ( p ≤ m )

    mod是取模(求余數(shù))的意思。事實(shí)上,這方法不僅可以對(duì)關(guān)鍵字直接取模,也可在折疊、平方取中后再取模。

    顯然在這里選取p的值至為關(guān)鍵,那么選取p值多少為合適呢?下面我們來舉個(gè)例子看看:有一個(gè)關(guān)鍵字,它有7個(gè)記錄。如果采用除留余數(shù)法,那么可以先嘗試將散列函數(shù)設(shè)計(jì)為f(key) = key mod 7的方法。比如12 mod 7= 5,所以它存儲(chǔ)在下標(biāo)為5的位置。

    地址0123456關(guān)鍵字722917111248

    不過這也是存在沖突的可能的,像7、14、21、28、35.....這些獲得的下標(biāo)都為零。

    如何合理選取p值? 使用除留余數(shù)法的一個(gè)經(jīng)驗(yàn)是,若散列表表長(zhǎng)為m,通常p為小于或等于表長(zhǎng)(最好接近m)的最小質(zhì)數(shù)或不包含小于20質(zhì)因子的合數(shù)。 舉個(gè)例子: 某散列表的長(zhǎng)度為100,散列函數(shù)H(k)=k%P,則P通常情況下最好選擇哪個(gè)作為p呢?答案是97。
    • 數(shù)字分析法 數(shù)字分析法即對(duì)關(guān)鍵字進(jìn)行分析,取關(guān)鍵字的若干位進(jìn)行或者組合進(jìn)行hash計(jì)算,這一類散列碼的特點(diǎn)是比較靈活,通常是結(jié)合其他hash函數(shù)來計(jì)算,可根據(jù)實(shí)際情況來做出調(diào)整,具有想當(dāng)?shù)撵`活性。

    有學(xué)生的生日數(shù)據(jù)如下:

    學(xué)生序號(hào)012345學(xué)生生日1975.10.031975.11.231975.03.021975.07.121975.04.211975.02.15

    經(jīng)分析,第一位,第二位,第三位、第四位重復(fù)的可能性大,取這四位造成沖突的機(jī)會(huì)增加,所以盡量不取前四位,取后四位比較好。
    • 隨機(jī)數(shù)法 選擇一個(gè)隨機(jī)函數(shù),取關(guān)鍵字的隨機(jī)函數(shù)值為它的哈希地址,即H(key)= random(key),其中random為隨機(jī)函數(shù)。通常,當(dāng)關(guān)鍵字長(zhǎng)度不等時(shí)采用此法構(gòu)造哈希函數(shù)較恰當(dāng)。
    • 平方取中法 取關(guān)鍵字平方后中間幾位作哈希地址。適于關(guān)鍵字長(zhǎng)度不統(tǒng)一的情況,而且對(duì)于元素連續(xù)的輸入,可以很好的將其散列均勻,而且相對(duì)于除法而言,乘法的執(zhí)行速度更快,這個(gè)由硬件決定。
    • 折疊法 將關(guān)鍵字分割成位數(shù)相同的幾部分(最后一部分的位數(shù)可以不同),然后取這幾部分的疊加和(舍去進(jìn)位)作為哈希地址,這方法稱為折疊法。
    例如:每一種西文圖書都有一個(gè)國(guó)際標(biāo)準(zhǔn)圖書編號(hào),它是一個(gè)10位的十進(jìn)制數(shù)字,若要以它作關(guān)鍵字建立一個(gè)哈希表,當(dāng)館藏書種類不到10,000時(shí),可采用此法構(gòu)造一個(gè)四位數(shù)的哈希函數(shù)。

    處理哈希沖突的方法

    基本原則: 從hash函數(shù)的要求可以看到,事實(shí)上我們只能定義對(duì)于兩個(gè)不同的輸入,輸出相同的概率盡可能小。

    • 開放地址法
      • 開放地址法有一個(gè)公式:Hi=(H(key)+di) MOD m i=1,2,...,k(k<=m-1)其中,m為哈希表的表長(zhǎng)。di是產(chǎn)生沖突的時(shí)候的增量序列。
    (1)-di值可能為1,2,3,...m-1,稱線性探測(cè)再散列。如果di取1,則每次沖突之后,向后移動(dòng)1個(gè)位置. (2)-di取值可能為1,-1,4,-4,9,-9,16,-16,...kk,-kk(k<=m/2)稱二次探測(cè)再散列。 (3)-di取值可能為偽隨機(jī)數(shù)列。稱偽隨機(jī)探測(cè)再散列。

    例如,在長(zhǎng)度為7的哈希表中已填有關(guān)鍵字分別為9、16的記錄(哈希函數(shù) H(key) = key MOD 7),現(xiàn)有第2個(gè)記錄,其關(guān)鍵字為16,由哈希函數(shù)得到哈希地址為2,產(chǎn)生沖突。若用線性探測(cè)再散列方法處理,得到下一個(gè)地址為3,仍沖突,繼續(xù)算4,不沖突,填入哈希表。若用二次探測(cè)再散列,則應(yīng)填入需要為1的位置。 線性探測(cè)再散列

    地址0123456關(guān)鍵字91716

    二次探測(cè)再散列

    地址0123456關(guān)鍵字16917

    • 多哈希法 設(shè)計(jì)多種哈希函數(shù),可以避免沖突,但是沖突幾率還是有的,函數(shù)設(shè)計(jì)的越好或越多都可以將幾率降到最低。
    • 拉鏈法 拉出一個(gè)動(dòng)態(tài)鏈表代替靜態(tài)順序存儲(chǔ)結(jié)構(gòu),可以避免哈希函數(shù)的沖突,不過缺點(diǎn)就是鏈表的設(shè)計(jì)過于麻煩,增加了編程復(fù)雜度。此法可以完全避免哈希函數(shù)的沖突。

    左邊很明顯是個(gè)數(shù)組,數(shù)組的每個(gè)成員包括一個(gè)指針,指向一個(gè)鏈表的頭,當(dāng)然這個(gè)鏈表可能為空,也可能元素很多。我們根據(jù)元素的一些特征把元素分配到不同的鏈表中去,也是根據(jù)這些特征,找到正確的鏈表,再從鏈表中找出這個(gè)元素。
    • 建立一個(gè)公共溢出區(qū) 這也是處理沖突的一種方法、假設(shè)哈希函數(shù)的值域?yàn)閇 0, m - 1 ],則設(shè)向量HashTable[ 0..m - 1 ]為基本表,每個(gè)分量存放一個(gè)記錄,另設(shè)向量OverTable[0..v]為溢出表。所有關(guān)鍵字和基本表中關(guān)鍵字為同義詞的記錄,不管它們由哈希函數(shù)得到的哈希地址是什么,一旦發(fā)生沖突,都填入溢出表。

    總結(jié)

    優(yōu)點(diǎn):

    • 不論哈希表中有多少數(shù)據(jù),查找、插入、刪除(有時(shí)包括刪除)只需要接近常量的時(shí)間即0(1)的時(shí)間級(jí)。實(shí)際上,這只需要幾條機(jī)器指令。
    • 哈希表運(yùn)算得非常快,在計(jì)算機(jī)程序中,如果需要在一秒種內(nèi)查找上千條記錄通常使用哈希表(例如拼寫檢查器)哈希表的速度明顯比樹快,樹的操作通常需要O(N)的時(shí)間級(jí)。哈希表不僅速度快,編程實(shí)現(xiàn)也相對(duì)容易。
    • 如果不需要有序遍歷數(shù)據(jù),并且可以提前預(yù)測(cè)數(shù)據(jù)量的大小。那么哈希表在速度和易用性方面是無與倫比的。

    缺點(diǎn):

    • 它是基于數(shù)組的,數(shù)組創(chuàng)建后難于擴(kuò)展,某些哈希表被基本填滿時(shí),性能下降得非常嚴(yán)重,所以程序員必須要清楚表中將要存儲(chǔ)多少數(shù)據(jù)(或者準(zhǔn)備好定期地把數(shù)據(jù)轉(zhuǎn)移到更大的哈希表中,這是個(gè)費(fèi)時(shí)的過程)。

    總結(jié)

    以上是生活随笔為你收集整理的ds哈希查找—二次探测再散列_大白话之哈希表和哈希算法的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。