用鏈表和數組實現HASH表,幾種碰撞沖突解決方法

?

?

  Hash算法中要解決一個碰撞沖突的辦法,后文中描述了幾種解決方法。下面代碼中用的是鏈式地址法,就是用鏈表和數組實現HASH表。

he/*hash table max size*/
#define HASH_TABLE_MAX_SIZE 40/*hash table大小*/
int hash_table_size=0;/*.BH-----------------------------------------------------------------
**                 結構體定義
**.EH-----------------------------------------------------------------
*/
/*hashTable結構*/
typedef int HashKeyType;
typedef struct{     OMS_TYPE__CurrFaultReport curr_fault_report;unsigned int begin_time[SYS_FAULT_REPORT_MAX_NUM];unsigned int end_time[SYS_FAULT_REPORT_MAX_NUM];unsigned int report_valid[SYS_FAULT_REPORT_MAX_NUM];
}HashValueType;typedef struct HashNode_Struct HashNode;
struct HashNode_Struct
{HashKeyType sKey;HashValueType nValue;HashNode* pNext;
};
HashNode* hashTable[HASH_TABLE_MAX_SIZE]; //hash table data strcutrue/*=================hash table function======================*/
/*.BH-----------------------------------------------------------------
**
**函數名:
**
**功能:string hash function
**
**參數: 無
**
**返回值:無
**
**設計注記:
**
**.EH-----------------------------------------------------------------
*/
unsigned int hash_table_hash_str(const char* skey)
{const signed char *p = (const signed char*)skey;unsigned int h = *p;if(h){for(p += 1; *p != '\0'; ++p){h = (h << 5) - h + *p;}}return h;
}/*.BH-----------------------------------------------------------------
**
**函數名:
**
**功能:insert key-value into hash table
**
**參數: 無
**
**返回值:無
**
**設計注記:
**
**.EH-----------------------------------------------------------------
*/
int hash_table_insert(const HashKeyType skey, HashValueType nvalue)
{unsigned int pos = 0;HashNode* pHead = NULL;HashNode* pNewNode = NULL;if (hash_table_size >= HASH_TABLE_MAX_SIZE){printf("out of hash table memory!\n");return 0;}pos = hash_table_hash_str(skey) % HASH_TABLE_MAX_SIZE;pHead = hashTable[pos];while (pHead){if (pHead->sKey == skey){printf("hash_table_insert: key %d already exists!\n", skey);return 0;}pHead = pHead->pNext;}pNewNode = (HashNode*)malloc(sizeof(HashNode));memset(pNewNode, 0, sizeof(HashNode));pNewNode->sKey = skey;memcpy(&pNewNode->nValue, &nvalue, sizeof(HashValueType));pNewNode->pNext = hashTable[pos];hashTable[pos] = pNewNode;hash_table_size++;return 1;
}/*.BH-----------------------------------------------------------------
**
**函數名:
**
**功能:lookup a key in the hash table
**
**參數: 無
**
**返回值:無
**
**設計注記:
**
**.EH-----------------------------------------------------------------
*/
HashNode* hash_table_find(const HashKeyType skey)
{unsigned int pos = 0;pos = hash_table_hash_str(skey) % HASH_TABLE_MAX_SIZE;if (hashTable[pos]){HashNode* pHead = hashTable[pos];while (pHead){if (skey == pHead->sKey)return pHead;pHead = pHead->pNext;}}return NULL;
}/*.BH-----------------------------------------------------------------
**
**函數名:
**
**功能:free the memory of the hash table
**
**參數: 無
**
**返回值:無
**
**設計注記:
**
**.EH-----------------------------------------------------------------
*/
void hash_table_release()
{int i;for (i = 0; i < HASH_TABLE_MAX_SIZE; ++i){if (hashTable[i]){HashNode* pHead = hashTable[i];while (pHead){HashNode* pTemp = pHead;pHead = pHead->pNext;if (pTemp){free(pTemp);}}}}
}//remove key-value frome the hash table
/*.BH-----------------------------------------------------------------
**
**函數名:
**
**功能:string hash function
**
**參數: 無
**
**返回值:無
**
**設計注記:
**
**.EH-----------------------------------------------------------------
*/
void hash_table_remove(const HashKeyType skey)
{unsigned int pos = hash_table_hash_str(skey) % HASH_TABLE_MAX_SIZE;if (hashTable[pos]){HashNode* pHead = hashTable[pos];HashNode* pLast = NULL;HashNode* pRemove = NULL;while (pHead){if (skey == pHead->sKey){pRemove = pHead;break;}pLast = pHead;pHead = pHead->pNext;}if (pRemove){if (pLast)pLast->pNext = pRemove->pNext;elsehashTable[pos] = NULL;free(pRemove);}}hash_table_size--;
}/*.BH-----------------------------------------------------------------
**
**函數名:
**
**功能:print the content in the hash table
**
**參數: 無
**
**返回值:無
**
**設計注記:
**
**.EH-----------------------------------------------------------------
*/
void hash_table_print()
{int i;printf("===========content of hash table===========\n");for (i = 0; i < HASH_TABLE_MAX_SIZE; ++i){if (hashTable[i]){HashNode* pHead = hashTable[i];printf("%d=>", i);while (pHead){printf("%d:%d  ", pHead->sKey, pHead->nValue.begin_time);pHead = pHead->pNext;}printf("\n");}}
}/*.BH-----------------------------------------------------------------
**
**函數名:
**
**功能:初始化系統名稱的hashTable,插入所有系統名稱
**
**參數: 無
**
**返回值:無
**
**設計注記:
**
**.EH-----------------------------------------------------------------
*/
void Common_InitHashTable()
{hash_table_size = 0;memset(hashTable, 0, sizeof(HashNode*) * HASH_TABLE_MAX_SIZE);
}

?

Hash碰撞沖突

Hash函數的作用就是保證對象返回唯一hash值,但當兩個對象計算值一樣時,這就發生了碰撞沖突。如下將介紹如何處理沖突,當然其前提是一致性hash。

1.開放地址法

開放地執法有一個公式:Hi=(H(key)+di) MOD m i=1,2,…,k(k<=m-1)
其中,m為哈希表的表長。di 是產生沖突的時候的增量序列。如果di值可能為1,2,3,…m-1,稱線性探測再散列。
如果di取1,則每次沖突之后,向后移動1個位置.如果di取值可能為1,-1,2,-2,4,-4,9,-9,16,-16,…k*k,-k*k(k<=m/2),稱二次探測再散列。
如果di取值可能為偽隨機數列。稱偽隨機探測再散列。

2.再哈希法

當發生沖突時,使用第二個、第三個、哈希函數計算地址,直到無沖突時。缺點:計算時間增加。
比如上面第一次按照姓首字母進行哈希,如果產生沖突可以按照姓字母首字母第二位進行哈希,再沖突,第三位,直到不沖突為止

3.鏈地址法(拉鏈法)

將所有關鍵字為同義詞的記錄存儲在同一線性鏈表中。如下:


因此這種方法,可以近似的認為是筒子里面套筒子

4.建立一個公共溢出區

假設哈希函數的值域為[0,m-1],則設向量HashTable[0..m-1]為基本表,另外設立存儲空間向量OverTable[0..v]用以存儲發生沖突的記錄。

優缺點:

優點:

①拉鏈法處理沖突簡單,且無堆積現象,即非同義詞決不會發生沖突,因此平均查找長度較短;
②由于拉鏈法中各鏈表上的結點空間是動態申請的,故它更適合于造表前無法確定表長的情況;
③開放定址法為減少沖突,要求裝填因子α較小,故當結點規模較大時會浪費很多空間。而拉鏈法中可取α≥1,且結點較大時,拉鏈法中增加的指針域可忽略不計,因此節省空間;
④在用拉鏈法構造的散列表中,刪除結點的操作易于實現。只要簡單地刪去鏈表上相應的結點即可。而對開放地址法構造的散列表,刪除結點不能簡單地將被刪結 點的空間置為空,否則將截斷在它之后填人散列表的同義詞結點的查找路徑。這是因為各種開放地址法中,空地址單元(即開放地址)都是查找失敗的條件。因此在 用開放地址法處理沖突的散列表上執行刪除操作,只能在被刪結點上做刪除標記,而不能真正刪除結點。

缺點:

指針需要額外的空間,故當結點規模較小時,開放定址法較為節省空間,而若將節省的指針空間用來擴大散列表的規模,可使裝填因子變小,這又減少了開放定址法中的沖突,從而提高平均查找速度。

?

開放地址法和拉鏈法是比較常用的兩種,各有優缺點,開放地址法的過程可以參考以下鏈接。

參考鏈接:HASH碰撞

轉載于:https://www.cnblogs.com/AndrewYin/p/9203621.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/280081.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/280081.shtml
英文地址,請注明出處:http://en.pswp.cn/news/280081.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

安卓操作sqlite3,增刪改查

創建 layout <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"android:orientation"vertical"android:layout_width"match_parent"android:layo…

基于.NetCore開發博客項目 StarBlog - (23) 文章列表接口分頁、過濾、搜索、排序

1前言上一篇留的坑&#xff0c;火速補上。在之前的第6篇中&#xff0c;已經有初步介紹&#xff0c;本文做一些補充&#xff0c;已經搞定這部分的同學可以快速跳過&#xff0c;基于.NetCore開發博客項目 StarBlog - (6) 頁面開發之博客文章列表對標準的WebApi來說&#xff0c;分…

如何在Chrome中保存您當前的所有標簽,以便以后閱讀

Chrome allows you to open tabs from your last browsing session when you open the browser. However, what if you want to save your current set of tabs to re-open at any time? Chrome doesn’t provide a way to do that natively, but there is an easy workaround…

ubuntu 16.04(Windows 10雙系統+grub引導)無法進入tt1~tt6(NVIDIA驅動安裝相關-黑屏,login loop,分辨率)...

目錄 前言回顧最終解決&#xff1a;0.關閉x服務1.禁用nouveau2.加入3.更新4.查找匹配驅動5.選擇推薦版本6.等待安裝后重啟,nvidia-smi查看是否安裝成功,或者lsmod | grep nvidia&#xff0c;成功結果如下7.重啟x服務8.此時還不能進入圖形界面&#xff0c;因為nomodeset還在&…

(備忘)打開office2010總是在配置進度

1、同時按上鍵盤上面的windows鍵和R鍵&#xff0c;出現“運行” 2、輸入“regedit”&#xff0c;回車進入注冊表 3、點擊“HKEY_CURRENT_USER”展開&#xff0c;依次“Software”--“Microsoft”--“Office”--"14.0"--"Word"展開&#xff0c;點擊"Op…

java、oracle對CLOB處理

oracle CLOB字段轉換位VARCHAR 1.實際上處理CLOB字段的時候&#xff0c;直接TO_CHAR&#xff0c;當長度超過4000的時候&#xff0c;會報錯&#xff0c;提示列被截取&#xff1b; CLOB轉varchar2&#xff1a;select to_char(CLOB字段) from table 2.直接使用SUBSTR對CLOB字段進行…

android 更改軟鍵盤_如何在Android的Google鍵盤上更改聲音和振動

android 更改軟鍵盤Tactile feedback from a touch screen keyboard is crucial, in my opinion, but I don’t like sounds when I tap keys. You may not be like me—maybe sounds are your thing, but vibration is annoying. Or maybe you dislike both (you rebel!). The…

『 再看.NET7』看看required屬性有什么不同

還是先看看C#中屬性的這定義&#xff0c;在初始化和訪問上有哪些方式&#xff0c;就能看出required屬性有什么不一樣的地方了。屬性&#xff0c;是封裝字段的&#xff0c;通過get和set訪問器可以很好地驗證數據的有效性。public record Order_00 {public Guid Id { get; set; }…

知識點:Mysql 索引原理完全手冊(1)

知識點&#xff1a;Mysql 索引原理完全手冊(1) 知識點&#xff1a;Mysql 索引原理完全手冊(2) 知識點&#xff1a;Mysql 索引優化實戰(3) 知識點&#xff1a;Mysql 數據庫索引優化實戰(4) Mysql-索引原理完全手冊 一、 介紹二、 索引的原理三、 索引的數據結構四、 聚集索引與輔…

如何將Apple Mail建議用于事件和聯系人

Apple products come preinstalled with an email client that can, on occasion, be quite smart. Today we want to show you another great feature: suggestions for event and contacts. Apple產品預裝了一個電子郵件客戶端&#xff0c;該客戶端有時可能非常聰明。 今天&a…

TPshop表結構

tp_account_log -- 賬戶表 字段名字段類型默認值描述log_idmediumint(8) unsigned 日志iduser_idmediumint(8) unsigned 用戶iduser_moneydecimal(10,2)0.00用戶金額frozen_moneydecimal(10,2)0.00凍結金額pay_pointsmediumint(9) 支付積分change_timeint(10) unsigned 變動時間…

Redis 通配符批量刪除key

問題&#xff1a; 線上有部分的redis key需要清理。 一、 由于Keys模糊匹配&#xff0c;請大家在實際運用的時候忽略掉。因為Keys會引發Redis鎖&#xff0c;并且增加Redis的CPU占用&#xff0c;情況是很惡劣的&#xff0c; 官網說明如下&#xff1a; Warning: consider KEYS as…

如何在 .Net 7 中將 Query 綁定到數組

在 .Net 7 中&#xff0c;我們可以通過綁定數組的方式來接收來自查詢字符串的參數。這樣就不需要再使用逗號分隔的字符串來獲取參數了。代碼演示 假設我們需要從 query 上接受多個 id 并返回查詢的結果。例如&#xff1a;id1&id2在 .Net 7 中&#xff0c;我們可以這樣實現&…

xbox one 越獄_如何在Xbox One上播放視頻和音樂文件

xbox one 越獄The Xbox One has integrated TV features and support for streaming media apps like Netflix and Hulu, but that isn’t where it ends. You can play video and music files you’ve ripped or downloaded by plugging in a USB drive or streaming them ove…

C++實驗七

11——3 #include<fstream>using namespace std;int main(){ ofstream file; file.open("test1.txt",ios_base::binary); file<<"已成功添加字符&#xff01;"; file.close(); return 0; } 11-4 #include<fstream>#include<iostrea…

Visual Studio 15.4發布,新增多平臺支持

微軟發布了Visual Studio 2017的第四個升級版本&#xff0c;并且延續了支持.NET Standard 2.0和通用Windows平臺&#xff08;UWP&#xff09;的承諾。.NET Standard 2.0支持是微軟推動跨平臺應用程序開發和代碼重用戰略的重要一環。\\15.4版本的變化與微軟發布的預覽版非常接近…

重新學習web后端開發-001-寫在前面的話

"長風破浪會有時 直掛云帆濟滄海" —— 李白<!-- more --> 1. 為什么會寫這個系列 隨著互聯網技術飛速的非常&#xff0c;web開發一直都是互聯網技術的重要部分之一。在作者十余年的工作中&#xff0c;經歷了從程序員到高級工程師&#xff0c;然后開始負責項目…

WPF-20 ICommand命令綁定

這節我們介紹一下WPF中比較重要的接口ICommand&#xff0c;也是WPF中一個新的特性&#xff0c;做過WinForm朋友都知道&#xff0c;WinForm開發是基于事件驅動開發模式&#xff0c;比如一個Button有Click事件&#xff0c;當我點擊該按鈕時&#xff0c;在當前頁面會執行具體的業務…

如何在Safari中查看網頁的完整URL

Modern versions of Safari don’t show the entire URL of a page in the address bar—it just shows the web site’s domain name. If this bothers you, it’s easy to change. Safari的現代版本無法在地址欄中顯示頁面的整個URL&#xff0c;而僅顯示網站的域名。 如果這困…

PHP | Uploading and reading of files and database 【PHP | 文件的上傳和讀取與數據庫】

這是我自己的一個作業&#xff0c;用的是很基礎的代碼。 有錯誤的地方歡迎批評和指正&#xff01; 這里最容易出錯的地方在讀取數據后向數據庫表中插入數據是的數據格式&#xff01; 文件上傳的頁面 uploading.php <html> <body align "center"> <fo…