有沒有一種方法時間複雜度,僅僅o(1)尼,那麼我們就要構造一種儲存結構,通過某種函式是之元素與它對應的關鍵碼之間能建立一一對映的關係,那麼自然通過之中一一對映的關係,我們就可以很快的找到我們需要的元素。
所以進入雜湊這個這題首先我們需要乙個我們下標,這個下表在雜湊當中
我們就稱之為雜湊位址。而這個位址我們可以通過雜湊函式的一些數學公式計算儲存下標,通過雜湊函式在對應雜湊位址裡面放對應的函式我們就叫之為雜湊表。
例如:雜湊函式設定為hash(key) = key % capacity
雜湊衝突:哎,這些副都帶的知識點介紹起來太麻煩了,就是通過雜湊函式計算粗來的陣列下標有兩個數同時滿足這個條件,同時都可以放入這個陣列下標。
這些計算雜湊位址的雜湊函式就不多說了,反正蠻多的,說複雜的也有簡單的也有
來看解決雜湊衝突的常見的兩種方式吧,閉雜湊,開雜湊。
閉雜湊:發生雜湊衝突時候,當雜湊表當中還有位置的時候,那麼把這個資料放入雜湊衝突的下乙個位置,而如何探測空位置就需要線性探測。
templateclass hashtable ;
public:
hashtable(size_t capacity = 3)
: _ht(capacity)
, _size(0)
bool insert(const pair& val)
// 插入元素
_ht[hashaddr]._state = exist;
_ht[hashaddr]._val = val;
_size++;
return true;
} int find(const k& key)
return hashaddr;
}
bool erase(const k& key)
return false;
} size_t size()const
bool empty() const
void swap(hashtable& ht)
private:
size_t hashfunc(const k& key)
private:
vector_ht;
size_t _size;
};
** 轉一圈也沒有找到,注意:動態雜湊表,該種情況可以不用考慮,雜湊表中元素個數到達 一定的數量,雜湊衝突概率會增大,需要擴容來降低雜湊衝突,因此雜湊表中元素是不會存滿的 **
線性探測優點:實現簡單
線性探測缺點:一旦發生雜湊衝突,所有的元素連線在一起容易產生資料堆積,即不同資料佔據可利用的空間位置,使得尋找某個關鍵碼的位置需要多次比較,導致搜尋效率降低。
二次線性探測
線性探測的缺陷是產生衝突的資料堆積在一塊,這與其找下乙個空位置有關係,因為找空位置的方式就 是挨著往後逐個去找,因此二次探測為了避免該問題,找下乙個空位置的方法為: = ( + )% m, 或者: = ( - )% m。其中:i = 1,2,3…, 是通過雜湊函式hash(x)對元素的關鍵碼 key 進行 計算得到的位置,m是表的大小。 對於2.1中如果要插入44,產生衝突,使用解決後的情況為:
注意:當表的長度為質數的且表裝載的表項一定能夠插入,而且任何乙個位置都不會被線性探測兩次,因此主要有一半的空位置,就不會存在表滿的問題。在搜尋時可以不考慮表裝滿的情況,但在插入是必須確保裝載因子a不超過0.5,如果超出必須考慮增容。
因此閉雜湊最大的缺點就是空間利用率比較低,這也是雜湊的缺陷。
開雜湊:首先有乙個關鍵碼集合,用雜湊函式計算雜湊位址,具有相同位址的關鍵碼歸於同乙個子集,每個子集當中和稱為乙個桶,每個同當中的元素的元素通過乙個單鏈表鏈結起來,個鍊錶當中的頭節點存在雜湊表當中。
從圖中可以看出開雜湊當中每個桶當中的元素都是發生雜湊衝突的元素。
template>
class hashbucket
// 雜湊桶中的元素不能重複
pnode* insert(const v& data)
// 3. 插入新元素
pcur = new node(data);
// 採用頭插法插入,效率高
pcur->_pnext = _ht[bucketno];
_ht[bucketno] = pcur;
_size++;
return pcur;
}
// 刪除雜湊桶中為data的元素(data不會重複),返回刪除元素的下乙個節點
pnode* erase(const v& data)
else
pret = pcur->_pnext;
delete pcur;
_size--;
return pret;
}
}
return nullptr;
}
// 查詢data是否在雜湊桶中
pnode* find(const v& data)
return nullptr;
}
size_t size()const
bool empty()const
void clear()
}_size = 0;
} bool bucketcount()const
void swap(hashbucket& ht)
~hashbucket()
private:
size_t hashfunc(const v& data)
private:
vector_ht;
size_t _size; // 雜湊表中有效元素的個數
};
開雜湊與閉雜湊比較:
應用鏈位址處理溢位,需要增設鏈結指標,似乎增加儲存開銷。事實上:由於開位址必須儲存大量的空閒空間一保證搜尋的效率,如二次探測法要求裝載因子a <= 0.7,而表項所佔空間又比指標的的多,所以使用鏈位址法反而比開位址發節省儲存空間。
雜湊衝突 閉雜湊與開雜湊
閉雜湊 也叫開放定址法,當發生雜湊衝突時,如果雜湊表未被裝滿,說明在雜湊表中必然還有空位置,那麼可以把key存放到衝突位置中的 下乙個 空位置中去。include using namespace std 雜湊表每個空間給個標記 empty此位置空,exist此位置已經有元素,delete元素已經刪除...
D OJ練習 雜湊查詢實驗(閉雜湊 開雜湊)
請設計乙個整型閉雜湊表,雜湊函式為除留餘數法,處理衝突時的探查方法為線性探查法,其中雜湊表的長度 除留餘數法的模和關鍵碼的個數由鍵盤輸入,再根據輸入由鍵盤輸入所有的關鍵碼。分別對三個待查值在雜湊表中進行查詢,如果找到了輸出位置,如果沒找到,輸出 none 並把該待查值插入到雜湊表中,如果雜湊表滿輸出...
雜湊表之開雜湊
了解雜湊基本看概念請看這裡 搜尋結構之雜湊 開雜湊完整 開雜湊 開雜湊每乙個位址的底層實現像乙個個的桶,所以又叫雜湊桶,同乙個桶中存放雜湊衝突的元素。通常,每個桶對應的鍊錶結點都很少,將n個關鍵碼通過某乙個雜湊函式,存放到雜湊表中的m個桶中,那麼每乙個桶中煉表的平均長度為n m,以搜尋平均長度為n ...