青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

專注于c++

  C++博客 :: 首頁 :: 聯(lián)系 :: 聚合  :: 管理
  21 Posts :: 0 Stories :: 4 Comments :: 0 Trackbacks

常用鏈接

留言簿(15)

我參與的團隊

搜索

  •  

最新評論

閱讀排行榜

評論排行榜

 

【摘要】

Hash是一種在信息學競賽中經(jīng)常用到的數(shù)據(jù)結構。一個好的Hash函數(shù)可以很大程度上提高程序的整體時間效率和空間效率。本文對面向各種不同標本(關鍵值)的Hash函數(shù)進行討論,并對多種常用的Hash函數(shù)進行了分析和總結。

 

【關鍵字】

Hash 函數(shù),字符串,整數(shù),實數(shù),排列組合

 

【正文】

對于一個Hash函數(shù),評價其優(yōu)劣的標準應為隨機性,即對任意一組標本,進入Hash表每一個單元(cell)之概率的平均程度,因為這個概率越平均,數(shù)據(jù)在表中的分布就越平均,表的空間利用率就越高。由于在競賽中,標本的性質(zhì)是無法預知的,因此數(shù)學推理將受到很大限制。我們用實驗的方法研究這個隨機性。

 

一、整數(shù)的Hash函數(shù)

常用的方法有三種:直接取余法、乘積取整法、平方取中法。下面我們對這三種方法分別進行討論。以下假定我們的關鍵字是 ,Hash表的容量是 ,Hash函數(shù)為 。

 

1.直接取余法

我們用關鍵字 除以 ,取余數(shù)作為在Hash表中的位置。函數(shù)表達式可以寫成:

例如,表容量 ,關鍵值 ,那么 。該方法的好處是實現(xiàn)容易且速度快,是很常用的一種方法。但是如果 選擇的不好而偏偏標本又很特殊,那么數(shù)據(jù)在Hash中很容易扎堆而影響效率。

對于 的選擇,在經(jīng)驗上,我們一般選擇不太接近 的一個素數(shù);如果關鍵字的值域較小,我們一般在此值域1.1~1.6倍范圍內(nèi)選擇。例如 的值域為 ,那么 即為一個不錯的選擇。競賽的時候可以寫一個素數(shù)生成器或干脆自己寫一個“比較像素數(shù)”的數(shù)。

我用4000個數(shù)插入一個容量為701Hash表,得到的結果是:

測試數(shù)據(jù)

隨機數(shù)據(jù)

連續(xù)數(shù)據(jù)

最小單元容量:

0

5

最大單元容量:

15

6

期望容量:

5.70613

5.70613

標準差:

2.4165

0.455531

 

可見對于隨機數(shù)據(jù),取余法的最大單元容量達到了期望容量的將近3倍。經(jīng)測試,在我的機器(Pentium III 866MHz,128MB RAM)上,該函數(shù)的運行時間大約是39ns,即大約35個時鐘周期。

 

2.乘積取整法

我們用關鍵字 乘以一個在 中的實數(shù) (最好是無理數(shù)),得到一個 之間的實數(shù);取出其小數(shù)部分,乘以 ,再取整數(shù)部分,即得 Hash表中的位置。函數(shù)表達式可以寫成:

;

其中 表示 的小數(shù)部分,即 。例如,表容量 ,種子 是一個實際效果很好的選擇),關鍵值 ,那么 。

同樣用4000個數(shù)插入一個容量為701Hash表( ),得到的結果是:

測試數(shù)據(jù)

隨機數(shù)據(jù)

連續(xù)數(shù)據(jù)

最小單元容量:

0

4

最大單元容量:

15

7

期望容量:

5.70613

5.70613

標準差:

2.5069

0.619999

 

從公式中可以看出,這個方法受 的影響是很小的,在 的值比較不適合直接取余法的時候這個方法的表現(xiàn)很好。但是從上面的測試來看,其表現(xiàn)并不是非常理想,且由于浮點運算較多,運行速度較慢。經(jīng)反復優(yōu)化,在我的機器上仍需892ns才能完成一次計算,即810個時鐘周期,是直接取余法的23倍。

 

3.平方取中法

我們把關鍵字 平方,然后取中間的 位作為Hash函數(shù)值返回。由于 的每一位都會對其平方中間的若干位產(chǎn)生影響,因此這個方法的效果也是不錯的。但是對于比較小的 值效果并不是很理想,實現(xiàn)起來也比較繁瑣。為了充分利用Hash表的空間, 最好取2的整數(shù)次冪。例如,表容量 ,關鍵值 ,那么

4000個數(shù)插入一個容量為512Hash表(注意這里沒有用701,是為了利用Hash表的空間),得到的結果是:

測試數(shù)據(jù)

隨機數(shù)據(jù)

連續(xù)數(shù)據(jù)

最小單元容量:

0

1

最大單元容量:

17

17

期望容量:

7.8125

7.8125

標準差:

2.95804

2.64501

 

效果比我們想象的要差,尤其是對于連續(xù)數(shù)據(jù)。但由于只有乘法和位運算,該函數(shù)的速度是最快的。在我的機器上,一次運算只需要23ns,即19個時鐘周期,比直接取余法還要快一些。

 

比較一下這三種方法:

 

實現(xiàn)難度

實際效果

運行速度

其他應用

直接取余法

較快

字符串

乘積取整法

較易

較好

浮點數(shù)

平方取中法

較好

 

從這個表格中我們很容易看出,直接取余法的性價比是最高的,因此也是我們競賽中用得最多的一種方法。

 

對于實數(shù)的Hash函數(shù),我們可以直接利用乘積取整法;而對于標本為其他類型數(shù)據(jù)的Hash函數(shù),我們可以先將其轉(zhuǎn)換為整數(shù),然后再將其插入Hash表。下面我們來研究把其他類型數(shù)據(jù)轉(zhuǎn)換成整數(shù)的方法。

二、字符串的Hash函數(shù)

字符串本身就可以看成一個256進制(ANSI字符串為128進制)的大整數(shù),因此我們可以利用直接取余法,在線性時間內(nèi)直接算出Hash函數(shù)值。為了保證效果, 仍然不能選擇太接近 的數(shù);尤其是當我們把字符串看成一個 進制數(shù)的時候,選擇 會使得該字符串的任意一個排列的Hash函數(shù)值都相同。(想想看,為什么?)

常用的字符串Hash函數(shù)還有ELFHash,APHash等等,都是十分簡單有效的方法。這些函數(shù)使用位運算使得每一個字符都對最后的函數(shù)值產(chǎn)生影響。另外還有以MD5SHA1為代表的雜湊函數(shù),這些函數(shù)幾乎不可能找到碰撞(MD5前一段時間才剛剛被破解)。

我從Mark Twain的一篇小說中分別隨機抽取了1000不同的單詞和1000不同的句子,作為短字符串和長字符串的測試數(shù)據(jù),然后用不同的Hash函數(shù)把它們變成整數(shù),再用直接取余法插入一個容量為1237Hash表,遇到?jīng)_突則用新字符串覆蓋舊字符串。通過觀察最后“剩下”的字符串的個數(shù),我們可以粗略地得出不同的Hash函數(shù)實際效果。

 

短字符串

長字符串

平均

編碼難度

直接取余數(shù)

667

676

671.5

P. J. Weinberger Hash

683

676

679.5

ELF Hash

683

676

679.5

較難

SDBM Hash

694

680

687.0

BKDR Hash

665

710

687.5

較易

DJB Hash

694

683

688.5

較易

AP Hash

684

698

691.0

較難

RS Hash

691

693

692.0

較難

JS Hash

684

708

696.0

較易

 

1000個隨機數(shù)用直接取余法插入容量為1237Hash表,其覆蓋單元數(shù)也只達到了694,可見后面的幾種方法已經(jīng)達到了極限,隨機性相當優(yōu)秀。然而我們卻很難選擇,因為不存在完美的、既簡單又實用的解決方案。我一般選擇JS HashSDBM Hash作為字符串的Hash函數(shù)。這兩個函數(shù)的代碼如下:

unsigned int JSHash(char *str)

{

unsigned int hash = 1315423911; // nearly a prime - 1315423911 = 3 * 438474637

while (*str)

{

hash ^= ((hash << 5) + (*str++) + (hash >> 2));

}

return (hash & 0x7FFFFFFF);

}

 

unsigned int SDBMHash(char *str)

{

unsigned int hash = 0;

while (*str)

{

// equivalent to: hash = 65599*hash + (*str++);

hash = (*str++) + (hash << 6) + (hash << 16) - hash;

}

return (hash & 0x7FFFFFFF);

}

 

JSHash的運算比較復雜,如果對效果要求不是特別高的話SDBMHash是一個很好的選擇。

 

三、排列的Hash函數(shù)

準確的說,這里我們的研究不再僅僅局限在“Hashing”的工作,而是進化到一個“numerize”的過程,也就是說我們可以在排列和1 的自然數(shù)之間建立一一對應的關系。這樣我們就可以利用這個關系來直接定址,或者用作Hash函數(shù);在基于狀態(tài)壓縮的動態(tài)規(guī)劃算法中也能用上。

 

1.背景知識

自然數(shù)的 進制表示法我們已經(jīng)很熟悉了,即:

,

比如 便是二進制數(shù), 便是十進制數(shù)。

引理 , 。

證明: 使用數(shù)學歸納法。

1)              時,等式顯然成立。

2)假設 時等式成立,即
時,

時等式亦成立。

3)綜上所述, , 成立。

把這個式子變形一下:

上式和 類似。不難證明,從0 的任何自然數(shù) 可唯一地表示為

其中 , 。甚至在式子后面加上一個 也無妨,在后面我們把這一項忽略掉。所以從0 個自然數(shù)與

*

一一對應。另一方面,不難從 算出 。

我們可以把序列 理解為一個“變進制數(shù)”,也就是第一位二進制,第二位三進制,……,第 進制,……,第 進制。這樣,我們就可以方便的使用類似“除 取余法”的方法從一個自然數(shù) 算出序列 。由于這樣的序列共有 個,我們很自然的想到把這 個序列和 個元素的全排列建立一一對應。

 

2.全排列與自然數(shù)之一一對應

為了方便起見,不妨設 個元素為 。對應的規(guī)則如下:設序列(*)對應的某一排列 ,其中 可以看做是排列 中數(shù) 所在位置右邊比 小的數(shù)的個數(shù)。以排列4213為例,它是元素1,2,3,4的一個排列。4的右邊比4小的數(shù)的數(shù)目為3,所以 。3右邊比3小的數(shù)的數(shù)目為0,即 。同理 。所以排列4213對應于變進制的301,也就是十進制的19;反過來也可以從19反推到301,再反推到排列4213

 

3.更一般性的排列

受到這個思路啟發(fā),我們同樣可以把更一般性的排列與自然數(shù)之間建立一一對應關系。想一想從 個元素中選 個的排列數(shù) 的公式是怎么來的?根據(jù)乘法原理,我們有

這是由于在排列的第1個位置有 種選擇,在排列的第2個位置有 種選擇,……,在排列的第 個位置有 種選擇。既然這樣,我們可以定義一種“m-n變進制數(shù)”,使其第1位是 進制,第2位是 進制,……,第 位是 進制。這樣,0 之間的任意一個自然數(shù) 都可以唯一地表示成:

其中 。注意到 (證明略,可直接變形結合前面的引理推得),所以從0 個自然數(shù)可以與序列

一一對應。類似地,可以用取余法從自然數(shù) 算出

我們設 個元素為 ,從中取出 個。對應關系如下:維護一個首元素下標為0的線性表 ,初始時 。對于某一排列 ,我們從 開始處理。首先在 中找到 的下標記為 ,然后刪除 ;接著在 中找到 的下標記為 ,然后刪除 ……直到 被刪除為止。以在5個元素1,2,3,4,5中取出2,4,3為例,這時 。首先在 中取出2,記下 , 變?yōu)?/span>1,3,4,5;在 中取出4,記下 , 變?yōu)?/span>1,3,5;在 中取出3,記下 變?yōu)?/span>1,5。因此排列243對應于“3-5變進制數(shù)”121,即十進制數(shù)19;反過來也可以從十進制數(shù)19反推到121,再反推到排列243。各序列及其對應的排列如下表:

123

000

0

341

220

30

124

001

1

342

221

31

125

002

2

345

222

32

132

010

3

351

230

33

134

011

4

352

231

34

135

012

5

354

232

35

142

020

6

412

300

36

143

021

7

413

301

37

145

022

8

415

302

38

152

030

9

421

310

39

153

031

10

423

311

40

154

032

11

425

312

41

213

100

12

431

320

42

214

101

13

432

321

43

215

102

14

435

322

44

231

110

15

451

330

45

234

111

16

452

331

46

235

112

17

453

332

47

241

120

18

512

400

48

243

121

19

513

401

49

245

122

20

514

402

50

251

130

21

521

410

51

253

131

22

523

411

52

254

132

23

524

412

53

312

200

24

531

420

54

314

201

25

532

421

55

315

202

26

534

422

56

321

210

27

541

430

57

324

211

28

542

431

58

325

212

29

543

432

59

 

【總結】

本文對幾個常用的Hash函數(shù)進行了總結性的介紹和分析,并將其延伸到應用更加廣泛的“與自然數(shù)建立一一對應”的過程。Hash是一種相當有效的數(shù)據(jù)結構,充分體現(xiàn)了“空間換時間”的思想。在如今競賽中內(nèi)存限制越來越松的情況下,要做到充分利用內(nèi)存空間來換取寶貴的時間,Hash能夠給我們很大幫助。我們應當根據(jù)題目的特點,選擇適合題目的數(shù)據(jù)結構來優(yōu)化算法。對于組合與自然數(shù)的一一對應關系,我還沒有想到好的方法,歡迎大家討論。

 

【參考文獻】

[1]    Thomas H Cormen, Charles E Leiserson, Ronald L Riverst, Clifford Stein. Introduction to Algorithms. Second Edition. The MIT Press, 2001

[2]    劉汝佳,黃亮. 《算法藝術與信息學競賽》. 北京:清華大學出版社,2004

[3]    盧開澄,盧華明. 《組合數(shù)學》(第3版). 北京:清華大學出版社,2002

 

【附錄】

常用的字符串Hash函數(shù)之源代碼:

// RS Hash Function

unsigned int RSHash(char *str)

{

    unsigned int b = 378551;

    unsigned int a = 63689;

    unsigned int hash = 0;

 

    while (*str)

    {

       hash = hash * a + (*str++);

       a *= b;

    }

 

    return (hash & 0x7FFFFFFF);

}

 

// JS Hash Function

unsigned int JSHash(char *str)

{

    unsigned int hash = 1315423911;

 

    while (*str)

    {

       hash ^= ((hash << 5) + (*str++) + (hash >> 2));

    }

   

    return (hash & 0x7FFFFFFF);

}

 

// P. J. Weinberger Hash Function

unsigned int PJWHash(char *str)

{

    unsigned int BitsInUnignedInt = (unsigned int)(sizeof(unsigned int) * 8);

    unsigned int ThreeQuarters    = (unsigned int)((BitsInUnignedInt * 3) / 4);

    unsigned int OneEighth        = (unsigned int)(BitsInUnignedInt / 8);

    unsigned int HighBits         = (unsigned int)(0xFFFFFFFF) << (BitsInUnignedInt - OneEighth);

    unsigned int hash             = 0;

    unsigned int test             = 0;

 

    while (*str)

    {

       hash = (hash << OneEighth) + (*str++);

       if ((test = hash & HighBits) != 0)

       {

           hash = ((hash ^ (test >> ThreeQuarters)) & (~HighBits));

       }

    }

 

    return (hash & 0x7FFFFFFF);

}

 

// ELF Hash Function

unsigned int ELFHash(char *str)

{

    unsigned int hash = 0;

    unsigned int x    = 0;

 

    while (*str)

    {

       hash = (hash << 4) + (*str++);

       if ((x = hash & 0xF0000000L) != 0)

       {

           hash ^= (x >> 24);

           hash &= ~x;

       }

    }

 

    return (hash & 0x7FFFFFFF);

}

 

// BKDR Hash Function

unsigned int BKDRHash(char *str)

{

    unsigned int seed = 131; // 31 131 1313 13131 131313 etc..

    unsigned int hash = 0;

 

    while (*str)

    {

       hash = hash * seed + (*str++);

    }

 

    return (hash & 0x7FFFFFFF);

}

 

// SDBM Hash Function

unsigned int SDBMHash(char *str)

{

    unsigned int hash = 0;

 

    while (*str)

    {

       hash = (*str++) + (hash << 6) + (hash << 16) - hash;

    }

 

    return (hash & 0x7FFFFFFF);

}

 

// DJB Hash Function

unsigned int DJBHash(char *str)

{

    unsigned int hash = 5381;

 

    while (*str)

    {

       hash += (hash << 5) + (*str++);

    }

 

    return (hash & 0x7FFFFFFF);

}

 

// AP Hash Function

unsigned int APHash(char *str)

{

    unsigned int hash = 0;

    int i;

 

    for (i=0; *str; i++)

    {

       if ((i & 1) == 0)

       {

           hash ^= ((hash << 7) ^ (*str++) ^ (hash >> 3));

       }

       else

       {

           hash ^= (~((hash << 11) ^ (*str++) ^ (hash >> 5)));

       }

    }

 

    return (hash & 0x7FFFFFFF);

}

posted on 2009-10-06 11:24 bellgrade 閱讀(6294) 評論(0)  編輯 收藏 引用 所屬分類: 數(shù)據(jù)結構算法
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            欧美99在线视频观看| 中国成人在线视频| 免费的成人av| 久久视频在线免费观看| 欧美一区二区三区免费观看视频| 亚洲制服av| 午夜精品一区二区三区电影天堂 | 久久精品av麻豆的观看方式| 亚洲欧美日韩久久精品| 午夜一区在线| 久久一区二区三区超碰国产精品| 久久九九精品99国产精品| 免费欧美在线| 国产精品美女一区二区在线观看| 国产乱人伦精品一区二区| 国产一区亚洲| 亚洲精品免费网站| 亚洲香蕉在线观看| 久久天天狠狠| 亚洲韩国青草视频| 亚洲国产高清一区| 99香蕉国产精品偷在线观看| 亚洲欧美不卡| 老鸭窝91久久精品色噜噜导演| 欧美精品在线视频观看| 久久精品系列| 在线视频欧美日韩精品| 久久精品盗摄| 亚洲国产精品ⅴa在线观看 | 久久精品国产第一区二区三区| 久久人人爽人人| 国产精品高潮呻吟久久av黑人| 国产日韩欧美一区二区三区在线观看| 在线精品一区二区| 午夜久久久久久| 欧美激情成人在线| 一区二区三区黄色| 欧美高清视频| 在线成人激情视频| 欧美一级久久久| 亚洲国产美女精品久久久久∴| 午夜精品久久久久久99热| 欧美日产国产成人免费图片| 国产原创一区二区| 午夜视频一区| 亚洲午夜av| 欧美视频精品在线| 91久久午夜| 久久免费黄色| 欧美一区二区三区在线观看视频| 国产精品白丝jk黑袜喷水| 99国产精品99久久久久久| 欧美高清在线视频观看不卡| 欧美一区二区视频在线观看2020| 国产精品私拍pans大尺度在线| 亚洲无限乱码一二三四麻| 亚洲破处大片| 欧美久久久久久蜜桃| 亚洲三级色网| 亚洲黄一区二区| 欧美激情一区三区| 99视频精品全部免费在线| 欧美www在线| 亚洲精品一区二| 久久久精彩视频| 怡红院精品视频在线观看极品| 久久女同精品一区二区| 久久国产乱子精品免费女 | 欧美国产视频一区二区| 久久久九九九九| 在线精品在线| 亚洲激情成人| 欧美日韩极品在线观看一区| 在线亚洲一区| 亚洲一区免费网站| 国产精品萝li| 久久精品国产欧美亚洲人人爽| 欧美一级日韩一级| 亚洲大片在线观看| 亚洲精品乱码久久久久久蜜桃麻豆| 欧美夫妇交换俱乐部在线观看| 猛男gaygay欧美视频| 最新日韩在线| 亚洲精品欧美专区| 国产精品美女久久久| 久久久蜜臀国产一区二区| 女生裸体视频一区二区三区| 亚洲三级网站| 亚洲视频图片小说| 在线观看亚洲精品视频| 亚洲国产第一| 国产精品日本一区二区| 久久影院午夜论| 欧美电影打屁股sp| 欧美一区国产在线| 久久免费精品视频| 亚洲一区www| 久久精品一区二区三区中文字幕| 亚洲国产成人av好男人在线观看| 日韩网站在线看片你懂的| 国产精品影音先锋| 欧美成人黑人xx视频免费观看| 亚洲精品免费一区二区三区| 韩日欧美一区| 亚洲看片免费| 黄色精品免费| 亚洲一级高清| 亚洲另类自拍| 欧美中日韩免费视频| 国产精品99久久久久久有的能看| 亚洲欧美日韩精品久久| 亚洲精品小视频| 性欧美超级视频| 亚洲无线视频| 欧美久久婷婷综合色| 久久久久中文| 国产精品丝袜白浆摸在线| 亚洲激情小视频| 狠狠色香婷婷久久亚洲精品| 中文网丁香综合网| 亚洲三级观看| 浪潮色综合久久天堂| 欧美在线三区| 国产精品第2页| 亚洲人精品午夜| 亚洲高清不卡在线观看| 久久精品av麻豆的观看方式| 亚洲欧美日韩国产另类专区| 欧美国产日韩精品免费观看| 美国三级日本三级久久99| 国产精品亚洲综合天堂夜夜| 亚洲精品在线视频观看| 91久久精品一区二区三区| 久久男人av资源网站| 欧美视频在线一区二区三区| 最新国产の精品合集bt伙计| 亚洲精品麻豆| 欧美国产日韩视频| 亚洲风情亚aⅴ在线发布| 极品尤物av久久免费看 | 欧美一区日本一区韩国一区| 欧美性猛交xxxx免费看久久久| 亚洲欧洲一区二区在线观看| 久久国产精品色婷婷| 欧美一区三区二区在线观看| 国产精品视频免费一区| 欧美午夜不卡在线观看免费 | 久久国产夜色精品鲁鲁99| 久久精品99无色码中文字幕| 国产日本欧洲亚洲| 久久精品免费观看| 欧美成人免费视频| 亚洲国产另类久久精品| 欧美成年视频| av成人国产| 性18欧美另类| 永久免费视频成人| 欧美激情四色| 亚洲午夜电影网| 久久久亚洲成人| 亚洲精品乱码久久久久久黑人| 欧美日韩一区二区三区视频| 亚洲综合成人婷婷小说| 久久婷婷综合激情| 亚洲靠逼com| 国产精品视频一| 久久久人成影片一区二区三区观看 | 99成人精品| 欧美一区二区三区在线看 | 午夜免费日韩视频| 模特精品在线| 在线亚洲观看| 激情欧美亚洲| 欧美日韩一区二区免费视频| 欧美一区二区三区啪啪| 91久久精品日日躁夜夜躁国产| 亚洲欧美另类国产| 亚洲国产精品精华液网站| 欧美网站在线| 久久夜色精品一区| 亚洲私拍自拍| 亚洲第一区在线观看| 午夜伦理片一区| 国产精品一卡二| 欧美大胆a视频| 欧美一区二区日韩| 日韩视频第一页| 男女激情视频一区| 亚洲欧美日韩精品久久| 亚洲国产专区校园欧美| 国产欧美一区二区三区视频| 欧美另类在线播放| 久久一区二区三区av| 亚洲资源在线观看| av成人免费| 亚洲激情成人在线| 久久亚洲午夜电影| 欧美一区二区三区四区在线观看地址 | 国产亚洲欧美在线| 欧美日韩在线观看一区二区|