1. 程式人生 > >查詢——圖文翔解HashTree(雜湊樹)

查詢——圖文翔解HashTree(雜湊樹)

在各種資料結構(線性表、樹等)中,記錄在結構中的相對位置是隨機的。因此在機構中查詢記錄的時需要進行一系列和關鍵字的比較。這一類的查詢方法建立在“比較”的基礎上。查詢的效率依賴於查詢過程中所進行的比較次數

之前我們介紹的各種基於比較的樹查詢演算法,這些查詢演算法的效率都將隨著資料記錄數的增長而下降。僅僅是有的比較慢(時間複雜度為O(n)),有的比較快(時間複雜度是O(logn))而已。這些查詢演算法的平均查詢長度是在一種比較理想的情況下獲得的。在實際應用當中,對資料結構中資料的頻繁增加和刪除將不斷地改變著資料的結構。這些操作將可能導致某些資料結構退化為連結串列結構,那麼其效能必然將下降。為了避免出現這種情況而採取的調整措施,又不可避免的增加了程式的複雜程度以及操作的額外時間。

雜湊表

理想的情況是希望不經過任何比較,一次存取便能得到所查的記錄,那就必須在記的儲存位置和它的關鍵字之間建立一個確定的對應關係f,使每個關鍵字和一個唯一的儲存位置相對應。因而在查詢時,只要根據這個對應關係f找到給定值K的像f(K)。由此,不需要進行比較便可直接取得所查記錄。在此,我們稱這個對應關係為雜湊(Hash)函式,按這個思想建立的表為雜湊表

在雜湊表中對於不同的關鍵字可能得到同一雜湊地址,這種現象稱做衝突。在一般情況下,衝突只能儘可能地減少,而不能完全避免。因為雜湊函式是從關鍵字集合到地址集合的映像。通常關鍵字的集合比較大,它的元素包括所有可能的關鍵字,而地址集合的元素僅為雜湊表中的地址值。在一般情況下,雜湊函式是一個壓縮映像函式
,這就不可避免的要產生衝突。


雜湊樹(HashTree)演算法就是要提供一種在理論上和實際應用中均能有效地處理衝突的方法。一般的雜湊(Hash)演算法都是O(1)的,而且基本是以空間換時間。這很容易導致對儲存空間無限制的需求。本文中雜湊樹(HashTree)演算法在實際操作中使用了一些技巧使得對空間的需求控制在一定範圍內。即空間需求僅和所需要儲存的物件個數有關,不會無限制地“膨脹”下去。

雜湊樹的理論基礎

質數分辨定理
簡單地說就是:n個不同的質數可以“分辨”的連續整數的個數和他們的乘積相等。“分辨”就是指這些連續的整數不可能有完全相同的餘數序列。
(這個定理的證明詳見:http://wenku.baidu.com/view/16b2c7abd1f34693daef3e58.html


例如:
從2起的連續質數,連續10個質數就可以分辨大約M(10) =2*3*5*7*11*13*17*19*23*29= 6464693230 個數,已經超過計算機中常用整數(32bit)的表達範圍。連續100個質數就可以分辨大約M(100) = 4.711930 乘以10的219次方。
而按照目前的CPU水平,100次取餘的整數除法操作幾乎不算什麼難事。在實際應用中,整體的操作速度往往取決於節點將關鍵字裝載記憶體的次數和時間。一般來說,裝載的時間是由關鍵字的大小和硬體來決定的;在相同型別關鍵字和相同硬體條件下,實際的整體操作時間就主要取決於裝載的次數。他們之間是一個成正比的關係。

插入

我們選擇質數分辨演算法來建立一棵雜湊樹。
選擇從2開始的連續質數來建立一個十層的雜湊樹。第一層結點為根結點,根結點下有2個結點;第二層的每個結點下有3個結點;依此類推,即每層結點的子節點數目為連續的質數。到第十層,每個結點下有29個結點。
同一結點中的子結點,從左到右代表不同的餘數結果。
例如:第二層結點下有三個子節點。那麼從左到右分別代表:除3餘0,除3餘1,除3餘2.
對質數進行取餘操作得到的餘數決定了處理的路徑

結點結構:結點的關鍵字(在整個樹中是唯一的),結點的資料物件,結點是否被佔據的標誌位(標誌位為真時,關鍵字才被認為是有效的),和結點的子結點陣列。
雜湊樹的節點結構

struct Node
{
    keyType      key ;
    ValueType    value ;
    bool         occupied ;    //用occupied來表示節點是否被佔據。如果節點的關鍵字(key)有效,那麼occupied應該設定位true,否則設定為false。
    struct Node* subNodes[1] ; //我們用subNodes[i]來表示節點的第i個子節點的地址。(此技術在跳躍表中有介紹,可翻看前面部落格)
} ;
(如果在建立當初就建立所有的節點,那麼所消耗的計算時間和磁碟空間是巨大的。在實際使用當中,只需要初始化根節點就可以開始工作。子節點的建立是在有更多的資料進入到雜湊樹中的時候建立的。因此可以說雜湊樹和其他樹一樣是一個動態結構。)


下面我們以隨機的10個數的插入為例,來圖解HashTree的插入過程,這個史上最清晰的圖解,你一定能看的明白^_^

有讀者可能有疑問,如果一直衝突下去怎麼辦?首先,若關鍵字是整型,我們的10層雜湊樹完全可以分辨出來它們,這是質數分辨演算法決定的。

(我們其實也可以把所有的鍵-值節點放在雜湊樹的第10層葉節點處,這第10層的滿節點數就包含了所有的整數個數,但是如果這樣處理的話,所有的非葉子節點作為鍵-值節點的索引,這樣使樹結構龐大,浪費空間)

【這裡沒有說的太清楚,此圖是以2開始的連續質數建立的,即:從上到下的層級中的每個節點中的子樹個數為2、3、5、7、11、13、17、19、23、29。第一層中的每個節點的子樹個數為2,第二層中的每個節點子樹個數為5.。。。。

上圖中的子樹上的數字,是其父節點的子樹指標陣列的索引值】

查詢

雜湊樹的節點查詢過程和節點插入過程類似,就是對關鍵字用質數序列取餘,根據餘數確定下一節點的分叉路徑,直到找到目標節點
如上圖,最小”雜湊樹(HashTree)在從4G個物件中找出所匹配的物件,比較次數不超過10次。也就是說:最多屬於O(10)。在實際應用中,調整了質數的範圍,使得比較次數一般不超過5次。也就是說:最多屬於O(5)。因此可以根據自身需要在時間和空間上尋求一個平衡點。

刪除

雜湊樹的節點刪除過程也很簡單,雜湊樹在刪除的時候,並不做任何結構調整。
只是先查到到要刪除的節點,然後把此節點的“佔位標記”置為false即可(即表示此節點為空節點,但並不進行物理刪除)。

優點

1、結構簡單

從雜湊樹的結構來說,非常的簡單。每層節點的子節點個數為連續的質數。子節點可以隨時建立。因此雜湊樹的結構是動態的,也不像某些雜湊演算法那樣需要長時間的初始化過程。雜湊樹也沒有必要為不存在的關鍵字提前分配空間。
需要注意的是雜湊樹是一個單向增加的結構,即隨著所需要儲存的資料量增加而增大。即使資料量減少到原來的數量,但是雜湊樹的總節點數不會減少。這樣做的目的是為了避免結構的調整帶來的額外消耗。

2、查詢迅速

從演算法過程我們可以看出,對於整數,雜湊樹層級最多能增加到10。因此最多隻需要十次取餘和比較操作,就可以知道這個物件是否存在。這個在演算法邏輯上決定了雜湊樹的優越性。
一般的樹狀結構,往往隨著層次和層次中節點數的增加而導致更多的比較操作。操作次數可以說無法準確確定上限。而雜湊樹的查詢次數和元素個數沒有關係。如果元素的連續關鍵字總個數在計算機的整數(32bit)所能表達的最大範圍內,那麼比較次數就最多不會超過10次,通常低於這個數值。 

3、結構不變

從刪除演算法中可以看出,雜湊樹在刪除的時候,並不做任何結構調整。這個也是它的一個非常好的優點。常規樹結構在增加元素和刪除元素的時候都要做一定的結構調整,否則他們將可能退化為連結串列結構,而導致查詢效率的降低。雜湊樹採取的是一種“見縫插針”的演算法,從來不用擔心退化的問題,也不必為優化結構而採取額外的操作,因此大大節約了操作時間。


缺點

1、非排序性

雜湊樹不支援排序,沒有順序特性。如果在此基礎上不做任何改進的話並試圖通過遍歷來實現排序,那麼操作效率將遠遠低於其他型別的資料結構。

關於超長字串的問題

如果是超長字串的關鍵字,該如何處理?若把它們按26進位制每一位都轉換為數字,則得到的結果太大。
我們可以用MD5等訊息壓縮演算法來生成定長的整數。

關於MD5

維基連結:http://zh.wikipedia.org/wiki/MD5
MD5(Message Digest Algorithm 訊息摘要演算法第五版)
一種被廣泛使用的密碼雜湊函式,可以產生出一個128位(16位元組)的雜湊值(hash value),用於確保資訊傳輸完整一致。

MD5演算法具有以下特點:
1、壓縮性:任意長度的資料,算出的MD5值長度都是固定的
2、容易計算:從原資料計算出MD5值很容易。
3、抗修改性:對原資料進行任何改動,哪怕只修改1個位元組,所得到的MD5值都有很大區別。
4、弱抗碰撞:已知原資料和其MD5值,想找到一個具有相同MD5值的資料(即偽造資料)是非常困難的。
5、強抗碰撞:想找到兩個不同的資料,使它們具有相同的MD5值,是非常困難的。
(1996年後被證實存在弱點,可以被加以破解,對於需要高度安全性的資料,專家一般建議改用其他演算法,如SHA-1)

對於超長字串,我們可以用MD5演算法生成一個128bit的整數,然後用RadixTree(翻看前面部落格)來儲存這個大整數,或者使用雜湊樹來儲存,對於這樣的大整數,我們不能簡單地使用計算機的整數來做除法,而是使用程式模擬人工的除法方式來做除法並獲得餘數。
這樣,使用MD5和選用更大的質數相結合的辦法。這樣就可以使得通過層次比較少的雜湊樹來獲得對關鍵字區間的完整覆蓋。這樣就減少了比較操作的次數,並提高整體的工作效率。

應用

雜湊樹可以廣泛應用於那些需要對大容量資料進行快速匹配操作的地方。例如:資料庫索引系統、簡訊息中的收條匹配、大量號碼路由匹配、資訊過濾匹配。雜湊樹不需要額外的平衡和防止退化的操作,效率十分理想。

【參考】

http://baike.baidu.com/view/10403049.htm
http://wenku.baidu.com/view/16b2c7abd1f34693daef3e58.html

----------------------------------

相關推薦

查詢——圖文HashTree

引 在各種資料結構(線性表、樹等)中,記錄在結構中的相對位置是隨機的。因此在機構中查詢記錄的時需要進行一系列和關鍵字的比較。這一類的查詢方法建立在“比較”的基礎上。查詢的效率依賴於查詢過程中所進行的比較次數。 之前我們介紹的各種基於比較的樹查詢演算法,這些查詢演算法的效率都將隨著資料記錄數的增長而下降。僅

查詢——圖文HashTree

引 在各種資料結構(線性表、樹等)中,記錄在結構中的相對位置是隨機的。因此在機構中查詢記錄的時需要進行一系列和關鍵字的比較。這一類的查詢方法建立在“比較”的基礎上。查詢的效率依賴於查詢過程中所進行的比較次數。 之前我們介紹的各種基於比較的樹查詢演算法,這些查詢演算法的效率都將隨著資料記錄數的增長而下降

圖文HashTree

引 在各種資料結構(線性表、樹等)中,記錄在結構中的相對位置是隨機的。因此在機構中查詢記錄的時需要進行一系列和關鍵字的比較。這一類的查詢方法建立在“比較”的基礎上。查詢的效率依賴於查詢過程中所進行的比較次數。 之前我們介紹的各種基於比較的樹查詢演算法,這些查詢演算法的效率

散列表及其儲存結構和特點詳

順序儲存的結構型別需要一個一個地按順序訪問元素,當這個總量很大且我們所要訪問的元素比較靠後時,效能就會很低。散列表是一種空間換時間的儲存結構,是在演算法中提升效率的一種比較常用的方式,但是所需空間太大也會讓人頭疼,所以通常需要在二者之間權衡。我們會在之後的具體演算法章節中得到更多的領悟。 什麼是散列表 讓我

資料結構與演算法25-散列表查詢

散列表查詢(雜湊表) 我們只需要能過某個函式f,使得儲存位置=f(關鍵字) 那樣我們可以通過查詢關鍵字不需要比較就可獲得需要的記錄的儲存位置。這就是一種新的儲存技術-----雜湊技術。 雜湊技術是在記錄的儲存位置和它的關鍵字之間建立一個確定的對應關係f,使得每個關鍵字key對應一個儲存位

散列表查詢的基本操作 完整程式碼

表和二叉樹的排序,是利用元素之間的關係,逐個查詢,或按一定的規律查詢。 而散列表(雜湊表),元素之間沒有關係,它是利用了元素與儲存地址之間的關係。 說白了,就是利用雜湊函式建立 元素->地址

散列表+衝突的解決方法

轉載http://www.nowamagic.net/academy/detail/3008060 1散列表 1簡單來說就是給一個key,就可以找到對應的key的儲存位置,就像身份證對應一個人一樣 儲存位置 = f(key) 2hashMap的key就是用到散列表 1.1雜湊衝突

兩數之和解法

給定一個整數陣列 nums 和一個目標值 target,請你在該陣列中找出和為目標值的 兩個 整數。 你可以假設每種輸入只會對應一個答案。但是,你不能重複利用這個陣列中同樣的元素。 示例: 給定 nums = [2, 7, 11, 15], tar

18.12.5 發現他,抓住他並查集&正方形

發現他,抓住他(10分) 題目內容: 一個城市中有兩個犯罪團伙A和B,你需要幫助警察判斷任意兩起案件是否是同一個犯罪團伙所為,警察所獲得的資訊是有限的。假設現在有N起案件(N<=100000),編號為1到N,每起案件由團伙A或團伙B所為。你將按時間順序獲得M條資訊(M<=100000

Redis常用操作-------Hash

1.HDEL key field [field ...] 刪除雜湊表 key 中的一個或多個指定域,不存在的域將被忽略。 在Redis2.4以下的版本里, HDEL 每次只能刪除單個域,如果你需要在一個原子時間內刪除多個域,請將命令包含在 MULTI

NOJ 48 小明的調查作業

描述小明的老師佈置了一份調查作業,小明想在學校中請一些同學一起做一項問卷調查,聰明的小明為了實驗的客觀性,想利用自己的計算機知識幫助自己。他先用計算機生成了N個1到1000之間的隨機整數(0<N≤1000),對於其

資料結構學習筆記七演算法

一、什麼是雜湊演算法        將任意長度的任意二進位制值串對映為固定長度的二進位制值串,這個對映的規則就是雜湊演算法,而通過原始資料對映之後得到的二進位制值串就是雜湊值。 雜湊演算法需要滿足的要求:

Qt5中自動匯入檔案生成ScatterChart

最近學習了QT中的Qchart的用法,想自動生成雜湊圖ScatterChart,同時自動讀取.txt、.dat檔案來獲得資料座標,以下是生成的一個小的demo檔案。 首先在.pro 中新增: QT += charts .h檔案如下: #ifndef CHARTVIEW

NYOJ 130 相同雪花入門

相同的雪花 時間限制:1000 ms | 記憶體限制:65535 KB 難度:4 描述 You may have heard that no two snowflakes are alike. Your task is to write a prog

POJ 1200 Crazy Search演算法【模板】

Many people like to solve hard puzzles some of which may lead them to madness. One such puzzle could be finding a hidden prime number i

[C++]資料結構:散列表函式構造、處理衝突

        關鍵字{12,25, 38, 15, 16, 29, 78, 67, 56, 21, 22, 47 } , 對應後位置是 {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}。 不過這種方法很容易產生衝突(如果關鍵字餘數大部分相同)。一般地,散列表長為m, 通常p

資料結構之散列表

今天學的是資料結構的雜湊查詢篇,其他的查詢可參見以前的傳送門 以前的查詢都是基於比較關鍵字的基礎上,所以查詢的效率依賴於查詢過程中所進行的比較次數。 理想的情況是不經過任何比較,通過計算就能直接得到記錄所在的儲存地址,雜湊查詢(Hashed Search)是

java資料結構和演算法09

  樹的結構說得差不多了,現在我們來說說一種資料結構叫做雜湊表(hash table),雜湊表有是幹什麼用的呢?我們知道樹的操作的時間複雜度通常為O(logN),那有沒有更快的資料結構?當然有,那就是雜湊表;   1.雜湊表簡介   雜湊表(hash table)是一種資料結構,提供很快速的插

漫畫 | 什麼是散列表

建立與輸入陣列相等長度的新陣列,作為直接定址表。兩數之和的期望是Target,將Target依次減輸入陣列的元素,得到的值和直接定址表比較,如果定址表存在這個值則返回;如果不存在這個值則將輸入陣列中的元素插入定址表,再進行輸入陣列中的下一個元素。 再進一步優化可以將輸入陣列直接作為直接定址

[資料結構][C++] 查詢和排序表儲存基本思想

雜湊表類概念摘要 雜湊表類SqHash的建立、查詢。設有若干個學生的考試成績,採用除留餘數求雜湊地址,將學生的資訊儲存到該地址空間,並且採用線性探測法解決衝突問題。 雜湊表又稱散列表。 雜湊表儲存的基本思想是:以資料表中的每個記錄的關鍵字 k為自變數,通過一種函式H(