散列表查找失敗平均查找長度_Python數據結構與算法56:排序與查找:沖突解決方案...

:本文如涉及到代碼,均經過Python 3.7實際運行檢驗,保證其嚴謹性。

本文閱讀時間約為6分鐘

前面說過,如果兩個數據項被散列映射到同一個槽,需要一個系統化的方法在散列表中保存第二個數據項,這個過程被稱為“解決沖突”。

如果散列函數是完美的,那就不會有散列沖突,但實際情況是,完美散列函數常常并不存在,解決散列沖突成為散列方法中很重要的一部分。

解決散列的一種方法就是,為沖突的數據項再找一個開放的空槽來保存。最簡單的就是從沖突的槽開始往后掃描,直到碰到一個空槽。如果到散列表尾部還未找到,則從首部接著掃描。

這種尋找空槽的技術被稱為“開放定址(open addressing)”。

向后逐個槽尋找的方法則是開放定址技術中的“線性探測(linear probing)”。

線性探測Linear Probing

還是以前面說過的這一組數據來作為示例說明線性探測具體如何操作。 假設有下列數據項:

54, 26, 93, 17, 77, 31

通過求余法我們得到了其散列值及對應槽號如下圖Pic-512-1的上半部分所示。

a6dcfab848c3e7cfb759c2218540e1c6.png

Pic-512-1 線性探測示例

現在,我們要做的是,把44、55、20三個數據項逐個插入到該散列表中。具體過程如下:

h(44)=0,但發現0#槽已被77占據,向后(向右)找到第一個空槽#1,把44保存在1#槽中。

h(55)=0,因為0#槽、1#槽均已被占據,后面的2#槽是空的,因此把55保存在2#槽中。

h(20)=9,發現9#槽已被31占據,向右,10#也被54占據,再從頭掃描,0#、1#、2#等槽均已被占據,后面的3#槽是空的,因此把20保存在3#槽中。

整個過程如上圖Pic-512-1所示。

需要注意的是,如果采用線性探測方法來解決散列沖突的話,那么散列表的查找也應該遵循同樣的規則。

如果在散列位置沒有找到查找項的話,就必須向后做順序查找,直到找到查找項或者碰到空槽(即查找失敗)。

線性探測的改進

線性探測法有一個缺點,就是有聚集的趨勢,即:如果同一個槽沖突的數據項較多的話,這些數據項就會在槽附近聚集起來,從而連鎖式影響其他數據項的插入。

為了避免這種不利的聚集趨勢,一種方法就是將線性探測擴展,從逐個探測改為跳躍式探測。比如,以+3的方式探測插入44、55、20。

還是用線性探測的例子來說明跳躍式探測是具體如何操作的。

還是假設有下列數據項:

54, 26, 93, 17, 77, 31

我們現在要把44、55、20三個數據項跳躍式(指定以+3的間隔)插入到該散列表中。具體過程如下:

h(44)=0,但發現0#槽已被77占據,向后+3個槽,找到#3槽。#3槽是空槽,可以存放數據,于是把44保存在3#槽中。

h(55)=0,因為0#槽,向后+3個槽,找到#3槽,已有數據項44;繼續向后+3個槽,找到#6槽,已有數據項17在里面;繼續向后+3個槽,找到#9槽,依然有數據項31占據著;繼續向右+3個槽,到了#1槽。#1槽為空,可以存放數據項,于是把55保存在#1槽中。

h(20)=9,發現9#槽已被31占據,向右+3個槽,找到1#槽,不為空;繼續向右+3個槽,找到#4,有26在里面;繼續向右+3個槽,#7槽為空,可以存放數據項,于是把20存放到#7槽中。

如下圖Pic-512-2所示:

5a2645b2712d7ae2b4b459b6d9cf1ddb.png

Pic-512-2 跳躍式探測示例

沖突解決方案:再散列rehashing

重新尋找空槽的過程可以用一個更為通用的“再散列rehashing”來概括:

newhashvalue = rehash(oldhashvalue)

對于線性探測來說,

rehash(pos) = (pos + 1) % sizeoftable

對于“+3”的跳躍式探測則是:

rehash(pos) = (pos + 3) % sizeoftable

跳躍式探測的再散列通式是:

rehash(pos) = (pos + skip) % sizeoftable

這里要注意的是,skip的取值不能被散列表大小整除,否則會產生周期,造成很多空槽永遠無法探測到的后果。如果把散列表的大小設為質數(如11),則可以避免這種情況。

除了將線性探測改善為跳躍式探測,還能將其變為“二次探測(quadratic probing)”。

二次探測是什么意思呢?就是對于

rehash(pos) = (pos + skip) % sizeoftable

來說,skip的值不再是固定的某個值,而是逐步增加的,如1、3、5、7、9等。 這樣槽號就會是原散列值以平方數增加:

h, h+1, h+4, h+9, h+16...

這也是一種能令散列值分散的好辦法。

沖突解決方案:數據項鏈Chaining

除了尋找空槽的開放定址技術之外,另一種解決散列沖突的方案是,將容納單個數據項的槽擴展為容納數據項集合(或者對數據項鏈表的引用)。

這樣,散列表中的每個槽就可以容納多個數據項,如果有散列沖突發生,只需要簡單地將數據項添加到數據項集合中。

查找數據項時則需要查找同一個槽中的整個集合。在同一個集合中查找,就用順序查找法。當然,隨著散列沖突的增加,對數據項的查找時間也會相應增加。

還是拿那組數據為例:

54, 26, 93, 17, 77, 31

要求插入44、55、20三個數據項。

如用數據項鏈的方法,每個槽都可以容納一個數據項的集合。操作示意如下圖Pic-512-3所示:

202d956e7aec3bc500657997ae50c13f.png

Pic-512-3 數據項鏈示例

To be continued.

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

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

相關文章

Face Alignment by 3000 FPS系列學習總結(一)

廣播: 如今的opencv已經提供了LBF的訓練和測試代碼,推薦閱讀 《使用OpenCV實現人臉關鍵點檢測》 face alignment 流程圖 train階段 測試階段 預處理 裁剪圖片 tr_data loadsamples(imgpathlistfile, 2); 說明: 本函數用于將原始圖片取…

acm常見算法及例題

1 acm常見算法及例題2 3 初期:4 一.基本算法:5 (1)枚舉. (poj1753,poj2965)6 (2)貪心(poj1328,poj2109,poj2586)7 (3)遞歸和分治法.8 (4)遞推.9 (5)構造法.(poj3295)10 (6)模擬法.(poj1068,poj2632,poj1573,poj2993,poj2996)11 二.圖算法…

2爬蟲基礎了解

1.什么是爬蟲爬蟲,即網絡爬蟲,大家可以理解為在網絡上爬行的一直蜘蛛,互聯網就比作一張大網,而爬蟲便是在這張網上爬來爬去的蜘蛛咯,如果它遇到資源,那么它就會抓取下來。想抓取什么?這個由你來…

js(function(){alert(‘’‘)})

function(){alert(sss)}是個匿名函數。沒有名字。所以沒有辦法調用。在外面加個括號,就變成了一個值,值的內容是函數的引用。例如var a (function(){"nop"})a 就是對這個函數的引用。有了名字,之后可以調用,例如a()現在…

macbook 移動硬盤無法寫入_如何升級MacBook筆記本的SSD硬盤-菜鳥折騰系列一

2010 年的時候買了 09 年末的 MACBOOK 小白,由于技術發展,軟件越來越吃硬件內存,現在2G 內存別提基本的工作了,連開機都有困難,每次一點就一個風火輪,基本就是一塊 13 寸的板磚了。。。眾所周知 HDD 機械硬…

face alignment by 3000 fps系列學習總結(二)

準備初始數據 mean_shape mean_shape就是訓練圖片所有ground_truth points的平均值.那么具體怎么做呢?是不是直接將特征點相加求平均值呢? 顯然這樣做是倉促和不準確的。因為圖片之間人臉是各式各樣的,收到光照、姿勢等各方面的影響。因此…

parasoft Jtest 使用教程:功能配置之查找錯誤

2019獨角獸企業重金招聘Python工程師標準>>> parasoft Jtest介紹和試用>>> 今天開始為大家帶來parasoft Jtest功能配置板塊教程,也是系列教程中最重要的一部分。 通過運行Jtest的BugDetective和使用最重要的一套規則來進行編碼標準靜態分析&…

kmp入門小結

void get_next(char *s) {int len strlen(s);int j 0; int k -1;while (j < len){if (k -1 || s[j] s[k]){j; k; next[j] k;}else k next[k];} } 設t next[i]; next[i] 表示的是 i之前最大的t滿足 s[0...t-1] s[i-t...i-1] 比如 0123 4 0123 5 &#xff0c;next[…

基于visual Studio2013解決面試題之0807strstr函數

&#xfeff;&#xfeff;&#xfeff;題目解決代碼及點評/*寫strstr函數簡單的遍歷去查找吧 */#include <iostream> #include <stdio.h>const char *my_strstr(const char *str, const char *sub_str) {// 遍歷for(int i 0; str[i] ! \0; i){int tem i; //tem保…

aop在項目中的實際運用_mypy在實際項目中的應用

我認為靜態類型似乎被吹捧過高了。盡管如此&#xff0c;mypy極低的侵入性能帶來許多好處。關于如何在現有的Python項目中添加類型&#xff0c;以下是我的一些想法&#xff0c;大致按重要性排序。首先確保mypy成功運行 Mypy上手時兩個很常見的問題有&#xff1a;1.Mypy沒有作為構…

face alignment by 3000 fps系列學習總結(三)

訓練 我們主要以3000fps matlab實現為敘述主體。 總體目標 我們需要為68個特征點的每一個特征點訓練5棵隨機樹&#xff0c;每棵樹4層深&#xff0c;即為所謂的隨機森林。 開始訓練 分配樣本 事實上&#xff0c;對于每個特征點&#xff0c;要訓練隨機森林&#xff0c;我們需…

HDU 2049 不容易系列之(4)——考新郎( 錯排 )

鏈接&#xff1a;傳送門思路&#xff1a;錯排水題&#xff0c;從N個人中選出M個人進行錯排&#xff0c;即 C(n,m)*d[m]補充&#xff1a;組合數C(n,m)能用double計算嗎&#xff1f;第二部分有解釋 Part 1. 分別求出來組合數的分子和分母然后相除/******************************…

級聯sql

select ID, PID, NAME,KEY from HS_DICT start with KEY HS_EXP_WORK_LOCATIONconnect by prior ID PID order by DISPLAYORDER轉載于:https://www.cnblogs.com/dazhaxie/p/3483532.html

獲取母版中的控件

1 通過findcontrol找控件ID需要在此事件中~因為Page_load中時是先內容頁加載然后才是母版頁加載 protected void Page_LoadComplete(object sender, EventArgs e) { Label2.Text "現在時間是" (Master.FindControl("Label1") as Label).Text; if (Reques…

linux服務器選ubantu或centos_如何通過SSH連接阿里云上的Linux系統

首先SSH是啥&#xff0c;維基一下&#xff1a;Secure Shell&#xff08;安全外殼協議&#xff0c;簡稱SSH&#xff09;是一種加密的網絡傳輸協議&#xff0c;可在不安全的網絡中為網絡服務提供安全的傳輸環境[1]。SSH通過在網絡中創建安全隧道來實現SSH客戶端與服務器之間的連接…

face alignment by 3000 fps系列學習總結

我們主要講一講Github上給出的matlab開源代碼《jwyang/face-alignment》的配置。 首先聲明&#xff1a;本人第一次配置的時候也是參考了csdn一個作者和github給出的說明配置成功的。其實后來想想很簡單的&#xff0c;但是可能對于初學者&#xff0c;還是有一定的困難。為此&am…

paypal之nodejs 框架 Kraken-js 源碼分析

本文是基于 kraken-js 0.6.1 版本的 關于如何使用kraken-js 可以去看看官網的使用文檔 點擊這里 。kraken-js 是基于express之上的&#xff0c;目的在于讓工程師更多的去關注代碼邏輯&#xff0c;少關注自身的開發環境&#xff0c;所以他將express所有的一些公用的配置都寫在了…

go build 參數_Go語言 通過go bulid -tags 實現編譯控制

Go語言提供的build tag 條件編譯特性&#xff0c;顧名思義&#xff0c;只有在特定條件下才會構建對應的代碼。比如下面的源文件只有在設置debug構建標志時才會被構建&#xff1a;// build debugpackage mainvar buildMode "debug"可以用以下命令構建&#xff1a;go …

selinux 的管理

第十單元selinux 的管理一 顯示及更改 SELINUX 模式getenforce ###顯示selinux模式setenforce 0|1 ##0指permissive警告&#xff0c;1 表示 enforcing強制###vim /etc/sysconfig/selinux ###修改selinux開機狀態###注&#xff1a;disable表示關閉&…

ubuntu15.10下安裝opencv2.4.9python上調用opencv庫

對于centos&#xff0c;可以參考&#xff1a;Install OpenCV-Python in Fedora 如果IPP難以下載可以在cmake時禁掉它&#xff0c;只需&#xff1a;cmake -DWITH_IPPOFF OpenCV3.3CUDA9.0 安裝過程中遇到的問題&#xff0c;解析&#xff1a; https://blog.csdn.net/u014613745/a…