寫在前面的話,本來看網上的面經就一直有關於雜湊表的問題,再加之實驗室同學頭條面試的時候讓實現乙個unordered_map,本來已經把對雜湊表的總結和實現提上日程了。奈何太懶,一天拖一天,直到自己面阿里的時候被面試官在雜湊表上翻來覆去蹂躪的時候,真的是不得不感嘆一句,活該!!!
業精於勤..
雜湊表,也稱雜湊表,是實現字典操作的一種有效的資料結構。儘管最壞情況下,雜湊表查詢乙個元素的時間與鍊錶中查詢的時間相同,達到了o(n)。然而在實際應用中,雜湊表查詢的效能是極好的。在一些合理的假設下,在雜湊表中可以查詢乙個元素的平均時間是o(1)
雜湊表的精髓在於雜湊二字上面,也就是數學裡面常用到的對映關係。它是通過雜湊函式將關鍵字對映到表中的某個位置上進行存放,以實現快速插入和查詢的。
為什麼需要雜湊函式?簡單來講,解決儲存空間的考慮。試想,將100個關鍵字存入大小為100的陣列裡,此時肯定是不需要雜湊函式的,一對一的放,肯定是可以實現的。但是當資料量增大,將1000個關鍵字,存入大小為100的陣列裡呢?此時乙個乙個的放,那剩下的怎麼辦呢,所以,我們需要某種計算方法,既能把這1000個關鍵字存進去,而且最主要是還能取出來。這就是雜湊函式要做的事,給每乙個關鍵字找乙個合適的位置,讓你既能存進去,還能把它取出來。注意,雜湊表裡一般存放的字典型別資料,即(key, value)的資料,是根據key去訪問value。
通過雜湊函式去計算雜湊值,難免會有衝突的時候,解決衝突的方法有如下幾種:
再雜湊法:使用多個雜湊函式,第乙個衝突時,使用第二個雜湊函式,直到不衝突為止
在使用開鏈法解決衝突問題時,將雜湊表內的元素稱為桶(bucket),大約意義是,**內的每個單元,涵蓋的不只是個節點(元素),甚至可能是一「桶」節點。
假設雜湊表中共有m個元素(桶),編號為0,1,..,m-1。 現在雜湊函式要做的就是將關鍵字對映到這m個桶中,盡量保證均勻。
最常用的是除留餘數法計算雜湊值:用乙個特定的質數來除所給定的關鍵字,所得餘數即為該關鍵字的雜湊值。
在此,仿stl的hashtable實現乙個簡化版的雜湊表,作為本文的結束。
採用開鏈法處理衝突,然後hashtable以vector作為底層陣列,鍵值型別的話,直接用template吧
雜湊表節點
雜湊表節點定義如下:
templatestruct hashtable_node;
桶裡的鍊錶也自己實現,不使用stl裡面提供的list,算是熟悉熟悉單鏈表吧。
雜湊表首先理清雜湊表需要的模板型別,key, value
只做最簡單的(key, value), key的型別考慮char, int, double, string
templateclass hashtable
//插入乙個關鍵字
void insert(t kv);
//根據鍵值刪除關鍵字
void erase(key key);
//判斷關鍵字是否在雜湊表中
bool find(key key);
//返回雜湊表中關鍵字個數
int size()
void printhashtable();
private:
//根據傳入大小判斷是否需要重新分配雜湊表
void resize(int num_elements);
//根據鍵值返回桶的編號
int buckets_index(key key, int size)
//根據節點返回鍵值
key get_key(t node)
private:
//使用stl list作桶
vectorbuckets;
//雜湊表中元素個數
size_t num_elements;
//雜湊函式
hashfunchash;
};
雜湊函式
雜湊函式的設計,由於只考慮了char, int, double, string四種型別,在使用模板類的話,可以通過template的偏特化特性直接為這四種型別設計特化版本。相關**如下
/*
* 雜湊函式的設定,只考慮 4 種鍵值型別的雜湊函式
* char, int , double , string
*/templatestruct hashfunc{};
template<> struct hashfunc < char >
};template<> struct hashfunc < int >
};template<> struct hashfunc < double >
e = ceil(log(dvalue));
return size_t((int64_max + 1.0) * tmp * exp(-e));
}};template<> struct hashfunc < string > ;
//找出最接近但大於的質數
inline unsigned long next_prime(unsigned long n)
//建構函式,初始化雜湊表
templatehashtable::hashtable()
//插入乙個關鍵字
templatevoid hashtable::insert(t kv)
//分配節點,插入
node *tmp = new node(kv);
tmp->next = head;
buckets[pos] = tmp;
num_elements++; //記錄個數
}//根據鍵值刪除關鍵字
template < class key, class value>
void hashtable::erase(key key)
else
} pre = head;
head = head->next; }}
//根據鍵值,判斷是否在雜湊表中
templatebool hashtable::find(key key)
return false;
}templatevoid hashtable::resize(int num_elements)
} //交換新舊雜湊表
buckets.swap(tmp);
}templatevoid hashtable::printhashtable()
}}
測試如下
以下為測試**:
#include"hashtable.h"
int main()
測試結果如圖:
雜湊表(雜湊表)的實現
雜湊函式直接用key size的形式,size為雜湊表的大小。衝突處理採用平方探測法,為保證可以探測到整個雜湊表空間,雜湊表大小設定為4k 3形式的素數。當雜湊表中的元素過多時會造成效能下降,這時應該倍增雜湊表的大小,重新計算原來雜湊表中每個元素在新的雜湊表中的位置。雜湊表的實現 hashtable...
雜湊表與雜湊函式 C實現
雜湊表 hash table,也叫雜湊表 是根據關鍵碼值 key value 而直接進行訪問的資料結構。也就是說,它通過把關鍵碼值對映到表中 乙個位置來訪問記錄,以加快查詢的速度。這個對映函式叫做雜湊函式,存放記錄的陣列叫做雜湊表。給定表m,存在函式f key 對任意給定的關鍵字值key,代入函式後...
雜湊表 雜湊表 的實現原理
雜湊表可以表述為,是一種可以根據關鍵字快速查詢資料的資料結構。通常情況下,不論雜湊表中資料有多少,增加,刪除,改寫資料的複雜度平均都是o 1 效率非常高。如果說每乙個資料它都對應著乙個固定的位置,那我們查詢特定乙個資料時,就可以直接檢視這個資料對應的位置是否存在資料。乙個形象的例子就是學生在教室中的...