• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            Jiang's C++ Space

            創(chuàng)作,也是一種學(xué)習(xí)的過程。

               :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::

            七、哈希表(Hash Table)及散列法(Hashing)

            數(shù)組的特點(diǎn)是:尋址容易,插入和刪除困難;而鏈表的特點(diǎn)是:尋址困難,插入和刪除容易。那么我們能不能綜合兩者的特性,做出一種尋址容易,插入刪除也容易的數(shù)據(jù)結(jié)構(gòu)?答案是肯定的,這就是我們要提起的哈希表,哈希表有多種不同的實(shí)現(xiàn)方法,我接下來解釋的是最常用的一種方法——拉鏈法,我們可以理解為“鏈表的數(shù)組”,如圖:


            左邊很明顯是個(gè)數(shù)組,數(shù)組的每個(gè)成員包括一個(gè)指針,指向一個(gè)鏈表的頭,當(dāng)然這個(gè)鏈表可能為空,也可能元素很多。我們根據(jù)元素的一些特征把元素分配到不同的鏈表中去,也是根據(jù)這些特征,找到正確的鏈表,再?gòu)逆湵碇姓页鲞@個(gè)元素。

            元素特征轉(zhuǎn)變?yōu)閿?shù)組下標(biāo)的方法就是散列法。散列法當(dāng)然不止一種,我下面列出三種比較常用的。

            1,除法散列法
            最直觀的一種,上圖使用的就是這種散列法,公式:
            index = value % 16
            學(xué)過匯編的都知道,求模數(shù)其實(shí)是通過一個(gè)除法運(yùn)算得到的,所以叫“除法散列法”。

            2,平方散列法
            求index是非常頻繁的操作,而乘法的運(yùn)算要比除法來得省時(shí)(對(duì)現(xiàn)在的CPU來說,估計(jì)我們感覺不出來),所以我們考慮把除法換成乘法和一個(gè)位移操作。公式:
            index = (value * value) >> 28
            如果數(shù)值分配比較均勻的話這種方法能得到不錯(cuò)的結(jié)果,但我上面畫的那個(gè)圖的各個(gè)元素的值算出來的index都是0——非常失敗。也許你還有個(gè)問題,value如果很大,value * value不會(huì)溢出嗎?答案是會(huì)的,但我們這個(gè)乘法不關(guān)心溢出,因?yàn)槲覀兏静皇菫榱双@取相乘結(jié)果,而是為了獲取index。

            3,斐波那契(Fibonacci)散列法

            平方散列法的缺點(diǎn)是顯而易見的,所以我們能不能找出一個(gè)理想的乘數(shù),而不是拿value本身當(dāng)作乘數(shù)呢?答案是肯定的。

            1,對(duì)于16位整數(shù)而言,這個(gè)乘數(shù)是40503
            2,對(duì)于32位整數(shù)而言,這個(gè)乘數(shù)是2654435769
            3,對(duì)于64位整數(shù)而言,這個(gè)乘數(shù)是11400714819323198485

            這幾個(gè)“理想乘數(shù)”是如何得出來的呢?這跟一個(gè)法則有關(guān),叫黃金分割法則,而描述黃金分割法則的最經(jīng)典表達(dá)式無疑就是著名的斐波那契數(shù)列,如果你還有興趣,就到網(wǎng)上查找一下“斐波那契數(shù)列”等關(guān)鍵字,我數(shù)學(xué)水平有限,不知道怎么描述清楚為什么,另外斐波那契數(shù)列的值居然和太陽(yáng)系八大行星的軌道半徑的比例出奇吻合,很神奇,對(duì)么?

            對(duì)我們常見的32位整數(shù)而言,公式:
            index = (value * 2654435769) >> 28

            如果用這種斐波那契散列法的話,那我上面的圖就變成這樣了:


            看起來不錯(cuò),以后就用斐波那契散列法吧。

            不過我們要注意了,前面提到的都是針對(duì)整數(shù)的散列法,那如果不是整數(shù)呢?下面給出一些參考算法,我把其它類型的數(shù)據(jù)轉(zhuǎn)變?yōu)?2位整數(shù),之后的處理前面已經(jīng)說了。

            1,浮點(diǎn)數(shù)的散列法

            unsigned int HashingDouble(double d)
            {
             
            if (d==0)
              
            return 0;
             
            else
             {
              
            int exponent;
              
            double mantissa = frexp(d, &exponent);
              
            return (unsigned int)((2*mantissa-1* (~0U));
             }
            }

            2,字符串的散列法

            unsigned int HashingString(char *str, int iLen)
            {
             unsigned 
            int hsval = 2654435769;
             
            int i;
             
            int iShift = 0;
             
            for(i=0; i<iLen; i++)
             {
              hsval 
            ^= (str[i]<<iShift);
              iShift
            +=3;
              
            if(iShift>24)
               iShift
            =0;
             }
             
            return hsval;
            }

            方法就提供那么多,遇到別的情況,比如說Unicode字符串,隨機(jī)應(yīng)變吧!

            posted on 2009-10-15 16:50 Jiang Guogang 閱讀(5470) 評(píng)論(3)  編輯 收藏 引用 所屬分類: Knowledge

            評(píng)論

            # re: 圖解數(shù)據(jù)結(jié)構(gòu)(5)——散列法及哈希表 2010-04-06 09:09 小弟
            嗯,長(zhǎng)見識(shí)了~~另外,哈希表只有求索引,怎么沒有求值的呢?  回復(fù)  更多評(píng)論
              

            # re: 圖解數(shù)據(jù)結(jié)構(gòu)(5)——散列法及哈希表[未登錄] 2012-02-24 14:46 andy
            請(qǐng)問為什么是 >>28,而不是其它數(shù)  回復(fù)  更多評(píng)論
              

            # re: 圖解數(shù)據(jù)結(jié)構(gòu)(5)——散列法及哈希表 2013-04-11 08:16 jiapei100
            因?yàn)?32-4 = 28, 而2^4=16,這里只用了16個(gè)索引! @andy
              回復(fù)  更多評(píng)論
              

            久久成人精品| 久久亚洲av无码精品浪潮| 亚洲中文字幕无码久久综合网| 四虎影视久久久免费| 日本强好片久久久久久AAA| 国产精品久久久久国产A级| 久久久久国色AV免费观看| 国产成人精品综合久久久久 | www.久久热.com| 色诱久久av| 久久99免费视频| 狠狠色丁香久久婷婷综合| 99久久99久久精品国产片果冻| 亚洲国产成人精品久久久国产成人一区二区三区综 | yy6080久久| 精品久久久久久久久久中文字幕 | 国产一区二区三精品久久久无广告| 性欧美大战久久久久久久| 国产一久久香蕉国产线看观看| 亚洲日本久久久午夜精品| 国产精品久久久久久久久久免费| 久久99久国产麻精品66| 久久无码一区二区三区少妇| 久久精品国产久精国产| 久久综合给久久狠狠97色| 久久丝袜精品中文字幕| 国产香蕉97碰碰久久人人| 国产精品欧美久久久天天影视 | 久久这里有精品| 亚洲国产成人久久综合碰| 欧美伊香蕉久久综合类网站| 久久久噜噜噜久久熟女AA片| 国内精品伊人久久久久777| 伊人久久国产免费观看视频| 亚洲国产成人久久综合区| 国内精品免费久久影院| 久久精品亚洲乱码伦伦中文| 久久AAAA片一区二区| 久久精品一区二区影院| 三级韩国一区久久二区综合 | 日日狠狠久久偷偷色综合免费|