雜湊查詢也稱為雜湊查詢。所謂的雜湊其實就是在記錄的儲存位置和記錄的關鍵字之間建立乙個確定的對應關係f,使得每個關鍵字key對應乙個儲存位置f(key)。查詢時,根據這個確定的對應關係找到給定值的對映f(key),若查詢集合中存在這個記錄,則必定在f(key)的位置上。雜湊技術既是一種儲存方法,也是一種查詢方法。示例**上傳至: 。
六種雜湊函式的構造方法:
(1)直接定址法
函式公式:f(key) = a * key + b(a,b為常數)
這種方法的優點是:簡單、均勻,不會產生衝突。但是需要事先知道關鍵字的分布情況,適合查詢表較小並且連續的情況。
(2)數字分析法
也就是取出關鍵字中的若干位組成雜湊位址。比如我們的11位手機號是「187****1234」,其中前三位是接入號,一般對應不同的電信公司。中間四位表示歸屬地。最後四位才表示真正的使用者號。
如果現在要儲存某個部門的員工的手機號,使用手機號碼作為關鍵字,那麼很有可能前面7位都是相同的,所以我們選擇後面的四位作為雜湊位址就不錯。
(3)平方取中法
取關鍵字平方後的中間幾位作為雜湊位址。由於乙個數的平方的中間幾位與這個數的每一位都有關,所以平方取中法產生衝突的機會相對較小。平方取中法所取的位數由表長決定。
如:k=456,k^2=207936,如果雜湊表的長度為100,則可以取79(中間兩位)作為雜湊函式值。
(4)摺疊法
摺疊法是將關鍵字從左到右分割成位數相等的幾個部分(最後一部分位數不夠可以短),然後將這幾部分疊加求和,並按雜湊表表長,取後幾位作為雜湊位址。當關鍵字位數很多,而且關鍵字中每一位上數字分布大致均勻時,可以使用摺疊法。
如:我們的關鍵字是9876543210,雜湊表表長三位,我們可以分為四組:987 | 654 | 321 | 0,然後將他們疊加求和:987+654+321+0 = 1962,再取後三位就可以得到雜湊位址為962.
(5)除留餘數法
選擇乙個適當的正整數p(p<=表長),用關鍵字除以p,所得的餘數可以作為雜湊位址。即:h(key) = key % p(p<=表長),除留餘數法的關鍵是選取適當的p,一般選p為小於或等於雜湊表的長度(m)的某個素數。
如:m = 8,p=7.
m = 16,p = 13.
m = 32,p = 31.
(6)隨機數法
函式公式:f(key) = random(key). 這裡的random是隨機函式,當關鍵字的長度不等時,採用這種方式比較合適。
總之,雜湊函式的規則就是:通過某種轉換關係,使關鍵字適度的分散到指定大小的順序結構中。越分散,查詢的時間複雜度就越小, 空間複雜度就越高。雜湊查詢明顯是一種以空間換時間的演算法。
上面提到了如何構造乙個雜湊函式,那就不得不提如何避免衝突的演算法。
(1)開放定址法
1.線性探測法
將雜湊看成乙個環形表,探測序列是(假設表長為m):
2.二次探測法
h2i-1 = (h(k)+i2) mod m
h2i = (h(k)-i2) mod m (1=< i <= (m-1)/2 )
優點:減少了堆集發生的可能性;
缺點:不容易探測到雜湊表空間。
3.偽隨機探測法
其中r1,r2,...,rm-1是乙個隨機排列。
(2)再雜湊法
當衝突發生時,使用另乙個函式計算得到乙個新的雜湊位址,直到衝突不再發生時為止。hi = rhi(key) i = 1,2,…,k 。其中rhi均是不同的雜湊函式。優點是不易產生聚集,缺點是增加了計算時間。
(3)鏈位址法
將所有關鍵字為同義詞的結點鏈結在同乙個單鏈表中。若選定的雜湊函式所產生的雜湊位址為0~m-1,則可以將雜湊表定義成乙個由m個煉表頭指標組成的指標陣列。優點是:不產生聚集;由於結點空間是動態申請的,故更適合造表前無法確定表長的情況;從表中刪除節點容易。
(4)公共溢位區法
假設雜湊函式的值域為[0...m-1],則設向量hashtable[0...m-1]為基本表,每個分量存放乙個記錄,另設立向量overtable[0..v]為溢位表。所有關鍵字和基本表中關鍵字為同義詞的記錄,不管它們由雜湊函式得到的雜湊位址是什麼,一旦發生衝突,都被填入溢位表中。
在雜湊表上進行查詢的過程和建表的過程基本一致。假設給定的值為k,根據建表時設定的雜湊函式h,計算出雜湊位址h(k),若表中該位址對應的空間未被占用。則查詢失敗。否則將該位址中的節點與給定值k比較,若相等則查詢成功,否則按建表時設定的處理衝突方法找下乙個位址,如此反覆下去,直到找到某個位址空間未被占用(查詢失敗)或者關鍵字比較相等(查詢成功)為止。
**如下:
//
// main.c
// hashsearch
//// created by chenyufeng on 16/2/17.
//#include "stdio.h"
#include "stdlib.h"
#define hashsize 7 // 定義雜湊表長為陣列的長度
#define nullkey -32768
typedef int status;
typedef structhashtable;
// 雜湊表表長,全域性變數
int m = 0;
void inithashtable(hashtable *hashtable);
status hash(int key);
void insert(hashtable *hashtable,int key);
status search(hashtable *hashtable,int key);
void displayhashtable(hashtable *hashtable);
int main(int argc, const char * argv) ;
//初始化雜湊表
inithashtable(&hashtable);
/*** 向雜湊表中插入資料;
也就是把元素使用雜湊函式對映到雜湊表中;
*/for (int i = 0;i < hashsize;i++)
//資料已存到雜湊表中,列印觀察雜湊表,元素的位置和原陣列是完全不一樣的
displayhashtable(&hashtable);
//查詢資料
result = search(&hashtable,30);
if (result == -1)else
return 0;
}//初始化乙個空的雜湊表
void inithashtable(hashtable *hashtable)
}//雜湊函式(除留餘數法)
status hash(int key)
//插入
void insert(hashtable *hashtable,int key)
//插入值
hashtable->elem[hashaddress] = key;
}//查詢
status search(hashtable *hashtable,int key)
}//查詢成功
return hashaddress;
}//列印結果
void displayhashtable(hashtable *hashtable)
printf("\n");
}
在c語言程式設計中,我們常常會設定一些預定義常量,或者說是函式的結果狀態碼,如下所示:
#define true 1
#define false 0
#define ok 1
#define error 0
#define infeasible -1
#define overflow -2
因為在c語言中是沒有bool布林這種資料型別的,所以上面的預定義可以簡化程式設計。我們有時候還會進行如下的預定義:
typedef int status;
表示status是函式的返回型別,其值是函式結果狀態**。我在上述**中也使用了這種預定義。
本文參考:
演算法學習 雜湊表及雜湊查詢
基於樹等的查詢方法,都是通過一系列對比來查詢的,查詢效率由比較一次所縮小的查詢範圍決定。而理想的查詢情況是直接根據關鍵碼得到其對應的資料元素位置。原理 將待儲存元素經過某一函式特定轉換為乙個值,將這個值作為位址,將這個待儲存元素存入這個位址中。當要查詢時,則將待查詢的元素經過同一轉換函式得到乙個轉換...
雜湊演算法學習
今天學習nosql資料庫的時候,學習到了memcached,但是對於雜湊演算法不太了解,這裡進行學習。什麼是雜湊演算法?把任意的二進位制字元轉換成固定長度的二進位制值得一種演算法。了解雜湊演算法前要了解雜湊表。什麼是雜湊表?也叫做雜湊表,根據key來訪問的一種資料結構 這個key value這個對映...
演算法學習 雜湊表
雜湊表 hash table,也叫雜湊表 是根據鍵 key 而直接訪問在記憶體儲存位置的資料結構。也就是說,它通過計算乙個關於鍵值的函式,將所需查詢的資料對映到表中乙個位置來訪問記錄,這加快了查詢速度。這個對映函式稱做雜湊函式,存放記錄的陣列稱做雜湊表。雜湊函式 hashfunction 若關鍵字為...