1. 程式人生 > >什麼是 雜湊表 HashMap 中陣列的 size 為什麼必須是 2 的整數次冪

什麼是 雜湊表 HashMap 中陣列的 size 為什麼必須是 2 的整數次冪

Hash,一般翻譯做“雜湊”,也有直接音譯為“雜湊”的,就是把任意長度的輸入(又叫做預對映, pre-image),通過雜湊演算法,變換成固定長度的輸出,該輸出就是雜湊值。這種轉換是一種壓縮對映,也就是,雜湊值的空間通常遠小於輸入的空間,不同的輸入可能會雜湊成相同的輸出,所以不可能從雜湊值來唯一的確定輸入值。簡單的說就是一種將任意長度的訊息壓縮到某一固定長度的訊息摘要的函式。

在程式設計實現中,常常面臨著兩個問題:儲存和查詢,儲存和查詢的效率往往決定了整個程式的效率。

腦補下,你在家裡忘記了指甲刀放在哪裡,通常要在你家所有抽屜中順序尋找,直到找到,最差情況下,有N個抽屜,你就要開啟N個抽屜。這種儲存方式叫陣列,查詢方法稱為「遍歷」。

腦補下,你是一個整理控,所有物品必須分門別類放入整理箱,再將整理箱編號,比如1號放入針線,2號放入證件,3號放入細軟。這種儲存和查詢方式稱為「雜湊」,如果這個時候要查詢護照,你不許要再翻所有抽屜,直接可在2號整理箱中獲取,通常只用一次查詢即可,如何編號整理箱,稱為雜湊演算法。

同樣是查詢,差距怎麼那麼大涅~,假設我們有100億條資料記錄,那差距就變得明顯,遍歷需要查詢最多100億次,最少1次,雜湊只需1次。

讓我們正式介紹雜湊和雜湊演算法,雜湊也稱雜湊,雜湊表是一種與陣列、連結串列等不同的資料結構,與他們需要不斷的遍歷比較來查詢的辦法,雜湊表設計了一個對映關係f(key)= address,根據key來計算儲存地址address,這樣可以1次查詢,f既是儲存資料過程中用來指引資料儲存到什麼位置的函式,也是將來查詢這個位置的演算法,叫做雜湊演算法。

讓我們舉個例子,比如下面這幾個人物,按陣列儲存:

程式設計師常說的「雜湊表」是個什麼鬼?

這樣我要找到大胸姐的電話號碼,需要順序查詢對比整個陣列,第一個餘罪,不是,第二個不是,第三個不是,直到第四個找到大胸姐。

如果以hash儲存呢?首先讓我們來看看如何設計雜湊演算法,雜湊演算法可以隨意設計,教科書上一般會說以下幾種方法:直接定址發,平方取中法,除數取餘法,雜湊演算法的本質上是計算一個數字,如果用這幾種方法講解會稍顯晦澀,我們假設我們的雜湊演算法是取姓名的首字母。所以f(餘罪) = y, f(傅老大) = f,f(沈嘉文) = s,f(大胸姐) = d。

構建的hash表如下:

程式設計師常說的「雜湊表」是個什麼鬼?

我們看到他們分別以姓名首字母的位置插入到這一張表格中,這樣我們構建了這樣一個Key-Value表格,此表就是雜湊表,也稱為Hash Table。未來,當我們要查詢餘罪的時候,通過計算,餘罪在y位置,可以通過1次查詢,找到這條記錄,也即手機號。

這個時候有客官問了,那以首字母為雜湊函式的話,應該有很多比如以y的姓名啊,這個時候就不是一次查找了吧,其實有很多條記錄都對映到一個位置上,稱為雜湊衝突。

雜湊衝突是跟雜湊函式的設計正相關的,你的隨機性越大,那麼產生雜湊衝突的可能性越小,在小概率下,如果還有衝突怎麼辦,這個時候要做些有損的設計,比如如果有兩個首字母為y的姓名,那麼可以接到餘罪的後面,當查詢的時候,需要先查詢到y,然後再順序查詢,如圖所示:

程式設計師常說的「雜湊表」是個什麼鬼?

還有一些解決雜湊衝突的辦法叫「雜湊再雜湊」,也就是針對第一次雜湊的結果再進行一次hash來減小衝突的概率。

這就是Hash表,首先Ta是一種資料結構,是一種效率極高的查詢方式,雜湊表的核心在於雜湊函式的設計,雜湊衝突了不要緊,我們要增加隨機性以及對衝突進行適當的有損化的處理

Hashmap的成員是Entry陣列 陣列大小16,2的次方;

因為put方法的實現是根據key的hashCode進行hash運算,得到值hash; 根據hash值去確定陣列的位置,hash& (table,length.-1)(效率高);hash%(table.length) length是2的次方 公式成立。 HashMap 有載入因子 比如0.75,預設是16,當時12時,自動擴容。
hashMap原始碼獲取元素的位置:
static int indexFor(int h, int length) {
    // assert Integer.bitCount(length) == 1 : "length must be a non-zero power of 2";
return h & (length-1);
}
解釋:
h:為插入元素的hashcode
length:為map的容量大小
&:與操作 比如 1101 & 1011=1001
如果length為2的次冪  則length-1 轉化為二進位制必定是11111……的形式,在於h的二進位制與操作效率會非常的快,
而且空間不浪費;如果length不是2的次冪,比如length為15,則length-1為14,對應的二進位制為1110,在於h與操作,
最後一位都為0,而0001,0011,0101,1001,1011,0111,1101這幾個位置永遠都不能存放元素了,空間浪費相當大,更糟的是這種情況中,陣列可以使用的位置比陣列長度小了很多,這意味著進一步增加了碰撞的機率,減慢了查詢的效率!這樣就會造成空間的浪費

相關推薦

什麼是 HashMap 陣列size 為什麼必須2整數

Hash,一般翻譯做“雜湊”,也有直接音譯為“雜湊”的,就是把任意長度的輸入(又叫做預對映, pre-image),通過雜湊演算法,變換成固定長度的輸出,該輸出就是雜湊值。這種轉換是一種壓縮對映,也就是,雜湊值的空間通常遠小於輸入的空間,不同的輸入可能會雜湊成相同的輸出,

【LeetCode】 hashmap(共88題)

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica } 【1】Two Sum  【3】Longest Substring Without Repeating Characters  【18】4Sum 

( hash ) ASL 和不成功 ASL 的計算

以下求解過程是按照“計算機統考的計算方法”,不同的老師、教材在“處理衝突”上可能會有不同的方法,所以最主要的是掌握原理即可,對於考研的朋友最好掌握統考真題的解題方法。 題目 例子:(2010年全國碩士研究生入學統一考試電腦科學與技術學科聯考計算機學科專業基礎綜合試題第一題) 將關鍵字序列(7、8

Leetcode442. 通過找出陣列重複元素

Leetcode442. Find All Duplicates in an Array 題目 Given an array of integers, 1 ≤ a[i] ≤ n (n = size of array), some elements

資料結構 5 /HashMap 、自動擴容、多執行緒會出現的問題

上一節,我們已經介紹了最重要的B樹以及B+樹,使用的情況以及區別的內容。當然,本節課,我們將學習重要的一個數據結構、雜湊表 ## 雜湊表 雜湊也常被稱作是散列表,為什麼要這麼稱呼呢,雜湊、雜湊、其元素分佈較鬆散、經常用來儲存例如`key-value`的資料、這樣有什麼好處呢?我們來細細琢磨一下: -

HashTable/散列表(線性探測和二探測)

HashTable的簡單介紹 HashTable是根據關鍵字直接訪問在記憶體儲存的資料結構。 HashTable叫雜湊表或者散列表。 它通過一個關鍵值的函式將所需的資料直接對映到表中的位置來訪問資料,這個對映函式叫雜湊函式(雜湊函式),存放記錄的陣列叫散列

wikioi-天梯-提高一等--2144:砝碼稱重2

題目描述 Description 有n個砝碼,現在要稱一個質量為m的物體,請問最少需要挑出幾個砝碼來稱? 注意一個砝碼最多隻能挑一次 輸入描述 Input Description 第一行兩個整數n和m,接下來n行每行一個整數表示每個砝碼的重量。

、JavaHashMap

雜湊演算法,是一類「演算法」。 雜湊表(Hash Table),是一種「資料結構」。 雜湊函式,是支撐雜湊表的一類「函式」。 Map是對映/地圖的意思,在Java中Map表示一種把K對映到V的「資料型別」。 HashMap,是Java中用雜湊表實現的一種「Ma

codewars打怪日記 Greed is Good JavaScript陣列用法和 的使用

codewars是一個線上程式設計網站,其獎勵機制像打怪升級。你不能檢視高於你級別的問題的答案。除非自己通過提交測試。通過提交之後可以看到各種解法排行榜 。通過對比自己解法和排行榜對比,可以找到差距,提高能力。      描述 : greed dice 是一個骰子游戲,使用

Hash(/)衝突處理及命中計算

前言   本片部落格主要講的是雜湊表中簡單的衝突處理的方法,以及命中率計算。原理方面基本沒有講解,基本就講個方法,主要用於知識記錄以及幫助一些刷題玩家瀏覽。   簡而言之,不講技術,只講方法。 引言   寫這篇部落格的契機是在刷pat甲級題遇到了一道寫雜湊的題目,結果英文太次被欺負了。之後靠翻譯讀懂題

powershell-陣列

陣列 建立陣列:陣列名=元素1,元素2,元素1;例如:$n=1,2,3,4,【注】陣列中的每個元素可以型別不一致 Count:檢視陣列的個數 -is [array]:判斷是否為陣列 訪問陣列 根據角標進行訪問;如:$

java的資料結構——

雜湊表 雜湊法是一個用於唯一標識物件並將每個物件儲存在一些預先計算的唯一索引(鍵)中的過程,因此, 物件以鍵值對的形式儲存,鍵值對的集合稱為字典,可以使用鍵搜尋每個物件。雜湊法有很多不同的數 據結構,但最常用的是雜湊表。 雜湊表通常使用陣列實現,它可以提供快速的查詢和插入操作,雜湊表不僅

資料結構和演算法精講版(陣列、棧、佇列、連結串列、遞迴、排序、二叉樹、紅黑樹、堆、)Java版

查詢和排序是最基礎也是最重要的兩類演算法,熟練地掌握這兩類演算法,並能對這些演算法的效能進行分析很重要,這兩類演算法中主要包括二分查詢、快速排序、歸併排序等等。我們先來了解查詢演算法! 順序查詢: 順序查詢又稱線性查詢。它的過程為:從查詢表的最後一個元素開始逐個與給定關鍵字比較,若某個記錄的關鍵字和給定值比較

C++STL的hash_map

map與hash_map map與hash_map都是在C++STL中常用的資料結構。 map:儲存資料結構是採用紅黑樹實現,提供了key-value的儲存和查詢功能,查詢速度可達log(n)。 hash_map:基於hash_table(雜湊表)儲存,相對map來說,他的查詢速度大大的

深入理解hashmap(三)和二叉搜尋樹的恩怨情仇

前面兩篇文章介紹了hashmap的原始碼和理論,今天把剩餘的部分紅黑樹講一下。理解好紅黑樹,對我們後續對hashmap或者其他資料結構的理解都是很有好處的。比方說為什麼後面jdk要把hashmap中的單鏈表更新成紅黑樹? 要理解紅黑樹首先要弄清楚普通二叉樹的一些基本概念 父節點和子節點,這個我就不多說了。

【JS】 存在重複元素 II #陣列 # Easy

給定一個整數陣列和一個整數 k,判斷陣列中是否存在兩個不同的索引 i 和 j,使得 nums [i] = nums [j],並且 i 和 j 的差的絕對值最大為 k。 輸入: nums = [1,2,3,1], k = 3 , 輸出: true 輸入: nums = [1,0,1,1],

【JS】 快樂數 # #陣列

編寫一個演算法來判斷一個數是不是“快樂數”。 一個“快樂數”定義為:對於一個正整數,每一次將該數替換為它每個位置上的數字的平方和,然後重複這個過程直到這個數變為 1,也可能是無限迴圈但始終變不到 1。如果可以變為 1,那麼這個數就是快樂數。 示例: 輸入: 19 輸出: true 解

資料結構與算法系列15()--散列表()

如何設計一個雜湊函式? 1.雜湊函式的設計不能太複雜,否則會消耗很多計算時間,也就影響了散列表的效能。 2.雜湊函式生成的值要儘可能的隨機並且均勻分佈,這樣才能最小化雜湊衝突,即便發生衝突,雜湊到每個槽裡的資料也會比較平均,不會出現某個槽裡資料太多的情況。 裝載因子的選擇 上一節

python 應用,常見函式 MD5和SHA2演算法

通過雜湊函式計算資料儲存 insert(key, value) 插入鍵值對 get(key) 獲取值 delete(key) 刪除值 常見雜湊函式 除法雜湊:h(k) = k % m 乘法雜湊:h(k) = floor(m*(

資料結構之與連結串列、陣列

雜湊表 主要描述雜湊表的定義:通過關鍵碼尋找值的資料對映結構,類似於查字典 當存在雜湊衝突時,有兩種常用的方式:開發定址法和鏈地址法 開發定址法通俗的來說就是判斷該地址是否存資料,沒存就放進去,存了就找下一個地址,依次類推,問題是如果空間不足,無法處理衝突。 鏈地