標籤:des style blog http 使用 strong
概念:散列表(Hash table,也叫雜湊表),是根據關鍵碼值(Key value)而直接進行訪問的資料結構。也就是說,它通過把關鍵碼值映射到表中一個位置來訪問記錄,以加快尋找的速度。這個映射函數叫做散列函數,存放記錄的數組叫做散列表。給定表M,存在函數f(key),對任意給定的關鍵字值key,代入函數後若能得到包含該關鍵字的記錄在表中的地址,則稱表M為雜湊(Hash)表,函數f(key)為雜湊(Hash) 函數
散列函數的選取:1. 直接定址法:取關鍵字或關鍵字的某個線性函數值為散列地址。即H(key)=key或H(key) = a·key + b,其中a和b為常數(這種散列函數叫做自身函數)。若其中H(key)中已經有值了,就往下一個找,直到H(key)中沒有值了,就放進去。2. 數字分析法:分析一組資料,比如一組員工的出生年月日,這時我們發現出生年月日的前幾位元字大體相同,這樣的話,出現衝突的幾率就會很大,但是我們發現年月日的後幾位表示月份和具體日期的數字差別很大,如果用後面的數字來構成散列地址,則衝突的幾率會明顯降低。因此數字分析法就是找出數位規律,儘可能利用這些資料來構造衝突幾率較低的散列地址。3. 平方取中法:取關鍵字平方後的中間幾位作為散列地址。4. 摺疊法:將關鍵字分割成位元相同的幾部分,最後一部分位元可以不同,然後取這幾部分的疊加和(去除進位)作為散列地址。數位疊加可以有移位疊加和間界疊加兩種方法。移位疊加是將分割後的每一部分的最低位對齊,然後相加;間界疊加是從一端向另一端沿分割界來回摺疊,然後對齊相加。5. 隨機數法:選擇一隨機函數,取關鍵字的隨機值作為散列地址,通常用於關鍵字長度不同的場合。6. 除留餘數法:取關鍵字被某個不大於散列表表長m的數p除後所得的餘數為散列地址。即 H(key) = key MOD p,p<=m。不僅可以對關鍵字直接模數,也可在摺疊、平方取中等運算之後模數。對p的選擇很重要,一般取素數或m,若p選的不好,容易產生同義字。
處理衝突的方式:1.開放定址法:出現衝突時採用線性試探、偽隨機試探等方式。2.公用溢出區法:將衝突元素直接放入公用溢出區(公用溢出區也可以進行散列).3.拉鏈法(鏈地址法):雜湊表的每個元素都是一個鏈表。出現衝突時直接掛到對應位置的鏈表上。4.在散列法:再準備若干雜湊函數,出現衝突時,使用其他雜湊函數進行散列。
實現:
線性雜湊表(採用了線性試探解決衝突問題)
/******************************線性hash表by Rowandjj2014/7/14******************************/#include<iostream>using namespace std;#define MAX 20//hash表大小typedef int DataType;typedef struct _NODE_{DataType data;//方便起見,直接用int型,實際應用時應該是任意類型的int flag;//1代表已有資料,0代表無資料}HashNode,*pHashNode;typedef struct _HASHTABLE_{pHashNode pHashNodeTemp;//實際儲存資料的hash數組int n;//hash表大小(總容量)int cur_elem;//當前容量}HashTable,*pHashTable;int hashFunc(DataType key)//hash函數{int index = key/3+1;index = (index < 0) ? -index : index;return index;}bool CreateHashTable(pHashTable pHashTableTemp);bool DestroyHashTable(pHashTable pHashTableTemp);void InsertHashTable(pHashTable pHashTableTemp,DataType data,int (*hashFunc)(DataType));int StatHashTable(HashTable HashTableTemp);//統計空項void PrintHashTable(HashTable HashTableTemp);//輸出hash表中的值int SearchKey(HashTable HashTableTemp,DataType data,int (*hashFunc)(DataType));//根據資料尋找其索引int main(){int i;int a[] = {9,31,26,1,13,2,11};cout<<"原始序列:"<<endl;for(i = 0; i < 7; i++){cout<<a[i]<<" ";}cout<<endl;HashTable hashTable;CreateHashTable(&hashTable);for(i = 0; i < 7; i++){InsertHashTable(&hashTable,a[i],hashFunc);}cout<<"散列後的序列:"<<endl;PrintHashTable(hashTable);DataType data;while(cin>>data){if(data == -1){break;}cout<<"index = "<<SearchKey(hashTable,data,hashFunc);}DestroyHashTable(&hashTable);return 0;}bool CreateHashTable(pHashTable pHashTableTemp){if(!pHashTableTemp){return false;}pHashTableTemp->pHashNodeTemp = (pHashNode)malloc(sizeof(HashNode)*MAX);if(!pHashTableTemp->pHashNodeTemp){return false;}else{pHashTableTemp->n = MAX;pHashTableTemp->cur_elem = 0;for(int i = 0; i < pHashTableTemp->n; i++){pHashTableTemp->pHashNodeTemp[i].flag = 0;pHashTableTemp->pHashNodeTemp[i].data = -1;}}return true;}bool DestroyHashTable(pHashTable pHashTableTemp){if(pHashTableTemp != NULL){free(pHashTableTemp->pHashNodeTemp);pHashTableTemp->pHashNodeTemp = NULL;pHashTableTemp->n = 0;}return true;}void InsertHashTable(pHashTable pHashTableTemp,DataType data,int (*hashFunc)(DataType)){if(!pHashTableTemp){return;}if(StatHashTable(*pHashTableTemp) == 0)//當hash表滿了的時候,可以選擇擴容,這裡直接返回 {cout<<"hash表已滿..."<<endl;return;}int index = hashFunc(data) - 1;while(pHashTableTemp->pHashNodeTemp[index].flag)//衝突時採用的是線性試探法{index = (index + 1)% pHashTableTemp->n;//防止越界}pHashTableTemp->pHashNodeTemp[index].data = data;pHashTableTemp->pHashNodeTemp[index].flag = 1;pHashTableTemp->cur_elem++;}int StatHashTable(HashTable HashTableTemp){int i,count = 0;for(i = 0; i < HashTableTemp.n; i++){if(HashTableTemp.pHashNodeTemp[i].flag == 0){count++;}}return count;}void PrintHashTable(HashTable HashTableTemp){int i;for(i = 0; i < HashTableTemp.n; i++){cout<<HashTableTemp.pHashNodeTemp[i].data<<" ";}cout<<endl;}int SearchKey(HashTable HashTableTemp,DataType data,int (*hashFunc)(DataType)){int index = hashFunc(data)-1;int times = 0;while(HashTableTemp.pHashNodeTemp[index].flag && HashTableTemp.pHashNodeTemp[index].data != data){index = (index + 1)% HashTableTemp.n;times ++;if(times == HashTableTemp.n){return -1;//沒找到}}return index;}
測試: