雜湊的故事 之 二次探測和hashtable

2021-10-09 23:24:30 字數 3045 閱讀 4399

雜湊真的給我留下了巨大的陰影

二次探測:若當前key與原來key產生相同的雜湊位址,則當前key存在該位址後偏移量為(1,2,3…)的二次方位址處

key1:hash(key)+0

key2:hash(key)+1^2

key3:hash(key)+2^2

···二次探測法中會每乙個空間採用乙個狀態標識來解決直接刪除帶來的問題,當刪除元素時將該對應空間設定為delete;在進行查詢某個元素時,判斷標識位如果是exist和delete就繼續往後探測查詢,直到遇到empty結束。

**實現:

//二次探測

#pragma once

#include

#include

using

namespace std;

enum state

;template

<

classk,

class

v>

struct hashtablenode

;template

<

class

k>

struct __hashfunc //預設的返回雜湊鍵值key的 仿函式};

//特化string的__hashfunc 仿函式

template

<

>

struct __hashfunc

return key;}}

;//實現雜湊表的key/value形式的二次探測

template

<

classk,

classv,

class

hashfunc

= __hashfunc>

class

hashtable}~

hashtable()

if(null

!= _states)

}bool

insert

(const k &key,

const v &value)

} _tables[index]

._key = key;

_tables[index]

._value = value;

_states[index]

= exist;

_size++

;return

true;}

node *

find

(const k &key)

else

// 被刪除 delete

} index =

_getnextindex

(index, i++);

if(index >= _capacity)

// 因為有填充因子 不為100% 不會出現全滿且key!=_key 導致死迴圈的情況

}return-1

;}bool

remove

(const k &key)

return

false;}

// 二次探測計算出存放位置

size_t _hashfunc

(const k &key)

// 雜湊衝突時 得到下乙個index的可以利用上乙個index的值 這樣能提高效率 比如 string的index計算就比較費時

size_t _getnextindex

(size_t prev, size_t i)

void

print()

else

if(_states[i]

== delete)

else}}

void

swap

(hashtable

&ht)

protected

:void

_checkcapacity()

// 擴容

}swap

(tmp);}

}protected

: node *_tables;

state *_states;

//狀態表

size_t _size;

size_t _capacity;

};

unordered_map本質是對hashtable封裝,所以這裡直接看hashtable的原始碼。

//rehash判斷

inline std::pair<

bool

, std::size_t>

prime_rehash_policy::

need_rehash

(std::size_t n_bkt, std::size_t n_elt, std::size_t n_ins)

const

else

}else

return std::

make_pair

(false,0

);}

用乙個 m_max_load_factor 的因子來判斷目前的容量需要多少個雜湊桶,如果需要 rehash,那麼使用素數表來算出新的桶需要多大。

素數表:

template

<

int ulongsize>

const

unsigned

long x

::primes[

256+48+

1]=m_deallocate_buckets

(m_buckets, m_bucket_count)

; m_bucket_count = n;

m_buckets = new_array;

}catch(.

..)}

乙個關於雜湊擴容的問題:如果我想在擴容的時候簡化雜湊的運算步驟,不需要重新對每乙個key進行重新雜湊運算,而是直接想要找到它在某個位置該怎麼做?

用位運算。

重新取餘計算index的花費是比較大的,位運算的引入可以大大降低計算的複雜度,具體可參考:

雜湊之閉雜湊(線性探測 二次探測)

hashtable.h include include include include common.h 雜湊表位置的狀態 typedef enum state state typedef int datatype typedef char datatype 轉換int函式指標 typedef si...

雜湊表之線性探測和二次探測

雜湊表又稱雜湊表。雜湊表儲存的基本思想是 以資料表中的每個記錄的關鍵字 k為自變數,通過一種函式h k 計算出函式值。把這個值解釋為一塊連續儲存空間 即陣列空間 的單元位址 即下標 將該記錄儲存到這個單元中。在此稱該函式h為哈函式或雜湊函式。按這種方法建立的表稱為雜湊表或雜湊表。處理衝突的方法 開放...

雜湊表KV形式的二次探測

雜湊表主要有兩種形式 1 key形式的,存入key的值,然後再去查詢key的值 2 key value形式的,存入key和對應的value的值,然後通過key來查詢value的值,主要可以來實現kv字典查詢 對於以上兩點本部落格並不都一一實現,而是僅僅實現kv形式的 其實庫中也有雜湊表這兩種的實現,...