開雜湊很簡單。asl的計算忘了,找了兩道題都沒算對,這才是我不寫的真正原因…**裡是裝13用的…
#include
using
namespace
std;
/* 雜湊表:
雜湊表(hash table,也叫雜湊表),是根據關鍵碼值(key value)而直接進行訪問的資料結構。也就是說,它通過把關
鍵碼值對映到表中乙個位置來訪問記錄,以加快查詢的速度。這個對映函式叫做雜湊函式,存放記錄的陣列叫做雜湊表。
兩種方式:
閉雜湊:若雜湊函式求出來相同的對映值,則把重複的元素存放在雜湊表的另乙個槽裡。
開雜湊:把發生衝突的關鍵碼儲存在雜湊表主表之外。
閉雜湊:
使用線性探測法舉例:對於a、b、c三個資料計算出來的key都是0。在插入的時候應該如下:
插入:
索引: 0 1 2 3
插入a: a
插入b: b(衝突,後移)
b插入c: c(衝突,後移)
c(衝突,後移)
c最終結果: a b c
查詢:
查詢的時候也是計算value得到key,然後使用和建立時相同的探測方法來向後尋值,直至找到或者遇到空。
比如查詢b,計算得到key為0,在第0位未尋到b,後移在第一位尋找到了b。
比如查詢d,計算得到key為0,在第0位未尋到d,後移三次之後遇到了空位,說明雜湊表裡沒有這個值。
刪除:刪除的時候不能簡單的把資料存放的位置置空。因為這可能影響到其他資料,
比如我刪除b,把第2位置空之後發現。然後我想查詢c,通過計算得到key是0,然後向後移動一位遇到空位,返回未找到。
實際上雜湊表裡是存在c的。所以在刪除的時候不能把原資料位置置空,而是設立乙個「墓碑」。
墓碑:標誌著這個槽之前存放過資料但現在不再使用了。
改進插入:
其實就乙個問題,插入的時候如果遇到了墓碑能直接插入嗎?答案當然是不能。正確的做法是遇到墓碑後記錄
第乙個墓碑所在的位置,然後向後遍歷直至遇到真正的空位置,在這個過程中如過存在資料和待插入資料一致。
則表示資料已存在,插入失敗。如果直接迴圈到了真正的空位置,表面資料不存在,把資料插入第乙個墓碑的
位置,如果全程為出現墓碑,插在當前空位置中。
開雜湊:
開雜湊就是陣列加鍊表的形式。從每個索引位置中引出乙個鍊錶,用以儲存發生衝突時的資料。這個是不需要設定墓碑的。
實現:下面的實現是基於開雜湊的實現。基於閉雜湊的實現請看我的另一篇文章。
至於說asl的計算等理論性問題可以去mooc或者在資料上尋找相關解釋,我的csdn部落格整個
dsa(data structure and algorithm)文集都是側重於計算機相關專業資料結構與演算法課程中遇到的演算法的實現。
*/#define max 1010
class node
};//雜湊值:最簡單的取餘法
int getkey(int val)
//插入
bool insert(node data, int val)
//刪除
bool del(node data, int val)
return
false;
}//查詢
bool find(node data, int val)
int main()
雜湊表(開雜湊)
hash table2.h pragma once include define hashmaxsize 1000 typedef int keytype typedef int valtype typedef size t hashfunc keytype key typedef struct h...
雜湊表 開雜湊
開雜湊 首先對關鍵碼集合用雜湊函式計算雜湊位址,具有相同位址的關鍵碼歸於同一子集合,每乙個子集合稱為乙個桶,各個桶中的元素通過乙個單鏈表鏈結起來,各鍊錶的頭結點儲存在雜湊表中。負載因子a不超過0.5 如果超出必須考慮增容 struct hashbucknode 結點 hashbucknode,pha...
雜湊表之開雜湊
了解雜湊基本看概念請看這裡 搜尋結構之雜湊 開雜湊完整 開雜湊 開雜湊每乙個位址的底層實現像乙個個的桶,所以又叫雜湊桶,同乙個桶中存放雜湊衝突的元素。通常,每個桶對應的鍊錶結點都很少,將n個關鍵碼通過某乙個雜湊函式,存放到雜湊表中的m個桶中,那麼每乙個桶中煉表的平均長度為n m,以搜尋平均長度為n ...