雜湊表的基本操作(一) 線性探測法解決雜湊衝突

2021-08-20 03:33:33 字數 4058 閱讀 8977

雜湊概念

在之前學習過的順序搜尋和二叉樹搜尋中,元素儲存位置和元素各關鍵碼之間沒有對應關係,因此在查詢乙個元素時,必須要經過關鍵碼的多次比較。搜尋的效率取決於搜尋過程中元素的比較次數。

我們希望可以不經過任何比較,一次直接從表中得到想要的元素,這樣一來,搜尋效率就有了質的提高。如果構造一種儲存結構,通過某種函式是元素的儲存位置與他的關鍵碼之間能夠建立一一對映的關係,那麼在查詢的時候通過該函式就可以很快的找到該元素。

當向該結構中:

插入元素時:根據待插入元素關鍵碼,以此計算出該元素的儲存位置進行存放

搜尋元素時:對元素的關鍵碼進行同樣的計算,把求的函式值當做元素的位置,在結構中按此位置取元素比較,若相等,則搜尋成功。

該方式即為雜湊(雜湊)方法,雜湊方法中使用的轉換函式稱為雜湊(雜湊)函式,構造出來的結構稱為雜湊表(雜湊表)。

雜湊衝突

我們使用同乙個雜湊函式來計算不止乙個的待存放的資料在表中的存放位置,總是會有一些資料通過這個轉換函式計算出來的存放位置是相同的,這就是雜湊衝突也就是說,不同的關鍵字通過同一雜湊轉換函式計算出相同的雜湊位址。

處理雜湊衝突針對雜湊衝突,這裡有兩種解決辦法:閉雜湊和開雜湊

閉雜湊:(開放位址法或者也叫線性探測法)

當我們要往雜湊表中插入乙個資料時,通過雜湊函式計算該值的雜湊位址,當我們找到雜湊位址時卻發現該位置已經被別的資料插入了,那麼此時我們就找緊跟著這一位置的下乙個位置,看是否能夠插入,如果能則插入,不能則繼續探測緊跟著當前位置的下乙個位置。

下面我們使用c語言來實現雜湊表的基本操作:

線性探測法實現:

檔案內容

#pragma once

#define max_size 1000

typedef

int keytype;

typedef

int valtype;

typedef

char datatype;

typedef

int (*hashfunc)(keytype key);

typedef

enum stat

stat;

typedef

struct hashelem

hashelem;

typedef

struct hashtable

hashtable;

//初始化

void hashinit(hashtable *ht,hashfunc hash_func);

//銷毀

void hashdestroy(hashtable *ht);

//插入資料

void hashinsert(hashtable *ht,keytype key,valtype value);

//查詢資料

int hashfind(hashtable *ht,keytype key,valtype *value);

//刪除資料

void hashremove(hashtable *ht,keytype key);

以下是對應函式的實現以測試結果:

//初始化

void hashinit(hashtable *ht,hashfunc hash_func)

ht->size = 0;

ht->func = hash_func;

int i = 0;

for(;i < max_size;i++)

}//銷毀

void hashdestroy(hashtable *ht)

//先將表中的每乙個位置都置為無效狀態

int i = 0;

for(;i < max_size;i++)

//再將有效元素個數清0

ht->size = 0;

//雜湊函式指向空

ht->func = null;

}//測試一下

void testinit()

測試結果:

//插入資料

void hashinsert(hashtable *ht,keytype key,valtype value)

//判定當前的hash表能否繼續插入

//假設負載因子為0.8

if(ht->size >= 0.8*max_size)

//由key計算offset(由hash函式計算出的存放位置的下標)

int offset = ht->func(key);

//但是該位置可能之前已經被別的資料佔據了

//所以我們需要先判斷當前計算出的位置是否能放入當前資料

//如果不能就從offset位置往後查詢

while(1)

//走到這裡說明當前計算出的位置

//不能放置當前待插入的資料

//判斷當前位置的元素是否和待插入的元素一樣

else

if(ht->data[offset].stat == valid \

&& ht->data[offset].key == key)

//則更新offset值繼續下一次迴圈往後查詢

else

}//else結束

}//while結束

}//列印雜湊表中的元素的函式

void hashprint(hashtable *ht,const

char *msg)

}printf("\n");

}//測試一下

void testinsert()

測試結果:

//查詢資料

int hashfind(hashtable *ht,keytype key,valtype *value)

//判斷當前hash表中是否有有效元素

if(ht->size == 0)

//由key值計算出offset

int offset = ht->func(key);

//從offset開始往後查詢

while(1)

//當前位置不是待查詢的元素

//則更新offset的值繼續查詢

else}}

else

if(ht->data[offset].stat == empty)

}//while迴圈結束

return0;}

//測試一下

void testfind()

測試結果:

//刪除資料

void hashremove(hashtable *ht,keytype key)

if(ht->size == 0)

//由key值計算出offset

int offset = ht->func(key);

//從offset開始往後找

while(1)

else

if(ht->data[offset].stat == empty)

else

}}//while迴圈結束

return;

}//測試一下

void testremove()

雜湊表 開放位址法之線性探測

雜湊表 優點 速度快 插入和查詢 缺點 基於陣列,不能有序的遍歷 鍵值對儲存方式,通過鍵來訪問值 hashmap.put key value 線性探測屬於開放位址法 線性探測插入演示 陣列最初狀態 在這組資料中要插入83 先對要插入資料雜湊化,雜湊化後的資料就是陣列下標,這裡雜湊化後的資料是23 然...

C語言 生成雜湊表 線性探測法

直接定址法 數字分析法 平方取中法 除留餘數法 隨機數法 開放定址法 線性探測法,二次探測法,隨機探測法 再雜湊函式法 鏈位址法 拉鍊法,雜湊桶 公共溢位區法 宣告定義 include include include define field 1 define null 32768 typedef ...

實驗一 線性表的基本操作

一 線性結構的順序表基本操作 實驗目的 1.學會定義單鏈表的結點型別 線性表的順序儲存型別,實現c程式的基本結構,對線性表的一些基本操作和具體的函式定義。2.掌握順序表的基本操作,實現順序表的插入 刪除 查詢以及求並集等運算。3.掌握對多函式程式的輸入 編輯 除錯和執行過程。實驗要求 1 預習c語言...