雜湊表的設計與實現

2022-07-16 17:09:14 字數 3372 閱讀 9095

寫在前面的話,本來看網上的面經就一直有關於雜湊表的問題,再加之實驗室同學頭條面試的時候讓實現乙個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 效率非常高。如果說每乙個資料它都對應著乙個固定的位置,那我們查詢特定乙個資料時,就可以直接檢視這個資料對應的位置是否存在資料。乙個形象的例子就是學生在教室中的...