數(shù)據(jù)結(jié)構(gòu):哈希表(根據(jù)數(shù)值查找的key-value容器)

1、定義

哈希表(或散列表)是利用哈希函數(shù)(散列函數(shù))把數(shù)據(jù)的存儲位置與關(guān)鍵字碼值關(guān)聯(lián)后大脉,直接根據(jù)關(guān)鍵字訪問數(shù)據(jù)的數(shù)據(jù)結(jié)構(gòu)。

2镰矿、為什么需要哈希表?

鏈表、棧棍矛、隊列抛杨、數(shù)組够委、字符串怖现、樹等數(shù)據(jù)結(jié)構(gòu)根據(jù)數(shù)值訪問任意元素都需要至少O(logn)的時間復(fù)雜度茁帽,缺少一種能夠根據(jù)數(shù)值在O(1)的復(fù)雜度快速訪問數(shù)據(jù)的數(shù)據(jù)結(jié)構(gòu)屈嗤。

3、特點

3.1饶号、優(yōu)點

根據(jù)關(guān)鍵字訪問元素的效率很高铁追;增刪查操作的效率很高茫船。

3.2、缺點

存在哈希沖突問題算谈,需要設(shè)計合理的哈希函數(shù)涩禀;存儲的數(shù)據(jù)是無序的,不適用于存儲需要排序的數(shù)據(jù)然眼;key不能重復(fù),不適用于存儲重復(fù)性高的數(shù)據(jù)高每。

4、常用哈希函數(shù)

4.1鲸匿、直接定址法

設(shè)計關(guān)鍵字key到散列地址的線性函數(shù)。例如f(key)=a*key+b晒骇;

4.2、數(shù)字分析法

如果任意關(guān)鍵字key由多位數(shù)字組成洪囤,則從中提取若干分布均勻且差異明顯的數(shù)字組成散列地址徒坡。

4.3瘤缩、平方取中法

如果無法確定關(guān)鍵字key中分布均勻的數(shù)字,則先計算關(guān)鍵字key的平方值剥啤,再取平方值的中間幾位組成散列地址锦溪。

4.4不脯、折疊法

如果關(guān)鍵字key的位數(shù)很多刻诊,則先將關(guān)鍵字分割為幾個等長的部分防楷,再取其疊加和的值(去除進位)組成散列地址则涯。

4.5复局、除留余數(shù)法

先設(shè)置一個常數(shù)P粟判,再對關(guān)鍵字key進行取余計算,余數(shù)key mod p作為散列地址档礁。

4.6角钩、隨機數(shù)法

選擇某個隨機函數(shù)計算關(guān)鍵字key的隨機值作為散列地址呻澜。

5、解決哈希沖突的方法

5.1易迹、開放尋址法

設(shè)置增量的探測序列依次查找散列表中的散列地址宰衙,直到在序列中查找的值未哈希沖突睹欲,將該值作為新的散列地址。

5.1.1窘疮、線性探測法

增量序列形如1袋哼,2闸衫,3,...蔚出,m-1弟翘,m為散列表長骄酗。

5.1.2稀余、偽隨機數(shù)法

增量序列為偽隨機數(shù)序列趋翻。

5.2、鏈地址法

將哈希沖突的散列地址存儲在鏈表中。

6师骗、Java代碼描述哈希表

package com.zy.demo.util;

import java.util.HashMap;
import java.util.Map;

/**
 * 哈希表
 * @author zy
 */
public class HashTableUtil{

    /**
     * HashMap是數(shù)組+單向鏈表+紅黑樹的復(fù)合數(shù)據(jù)結(jié)構(gòu)。
     *
     * HashMap擴容(即rehash過程)需要重建一整套數(shù)組+單向鏈表+紅黑樹辟癌,非常影響迭代性能。
     * 避免或減少rehash是維持HashMap高性能的關(guān)鍵因素愿待。
     *
     * HashMap使用直接地址法定義哈希函數(shù)靴患。
     * 哈希函數(shù)f(key) = (capacity-1) & h(key)仍侥。
     * capacity:數(shù)組容量鸳君。
     * h(key):計算key哈希碼的函數(shù)农渊。h(key) = key.hashCode() ^ (key.hashCode() >>> 16)
     *
     * 基礎(chǔ)數(shù)據(jù)通過哈希函數(shù)存儲在數(shù)組對應(yīng)位置或颊,每個數(shù)組的元素是一個單向鏈表砸紊。
     * 當新添加的數(shù)據(jù)發(fā)生哈希沖突囱挑,則該數(shù)據(jù)會通過鏈地址法,存儲在鏈表的下個結(jié)點平挑。
     *
     * 當鏈表長度大于等于8時,單向鏈表結(jié)構(gòu)會轉(zhuǎn)化為紅黑樹結(jié)構(gòu)通熄;當紅黑樹按照擴容哈希算法(hash & capacity)計算的結(jié)點數(shù)小于等于6時唆涝,紅黑樹結(jié)構(gòu)會轉(zhuǎn)化為單向鏈表結(jié)構(gòu)唇辨。
     *
     * HashMap增刪查的時間復(fù)雜度:
     * 無哈希沖突:O(1)
     * 有哈希沖突:出現(xiàn)紅黑樹結(jié)構(gòu)是O(logn);未出現(xiàn)紅黑樹結(jié)構(gòu)是O(1)
     * 數(shù)組的時間復(fù)雜度:O(1)
     * 鏈表的時間復(fù)雜度:O(1)赏枚,因為鏈表最大長度是8亡驰,是有限值饿幅,即O(1)隐解。
     * 紅黑樹的時間復(fù)雜度:O(logn),紅黑樹可以看作是平衡的二叉搜索樹诫睬。
     *
     */
    private Map<Object,Object> map;

    public HashTableUtil(){
        this.map = new HashMap<>();
    }

    /**
     * 計算指定字符串被提交的次數(shù)
     * 時間復(fù)雜度:哈希沖突少的情況下是O(1);哈希沖突多的情況下是O(logn)。
     * 空間復(fù)雜度:O(n) --新建HashMap對象
     * @return 次數(shù)
     */
    public int calcKeySubmit(String key){
        //入?yún)⑿r?        if(key == null){
            return -1;
        }
        //獲取指定字符串的提交次數(shù)
        Integer count = (Integer) map.get(key);
        //如果字符串第一次被提交蚓曼,次數(shù)為1;否則次數(shù)累加纫版。
        count = count == null ? 1 : count+1;
        //記錄當前字符串新的提交次數(shù)
        map.put(key,count);
        return count;
    }

    /**
     * 給定一個已去重的正整數(shù)數(shù)組arr和一個目標值target,請在數(shù)組中找出相加結(jié)果等于目標值的兩個整數(shù)客情,并返回它們在數(shù)組中的下標。
     * 假設(shè)答案只有一組且數(shù)據(jù)中的元素只能使用1次膀斋。
     * 時間復(fù)雜度:哈希沖突少的情況下是O(1);哈希沖突多的情況下是O(logn)仰担。
     * 空間復(fù)雜度:O(n) --新建HashMap對象
     */
    public static void findTwoSum(int[] arr,int target){
        //校驗正整數(shù)數(shù)組
        if(arr == null || arr.length < 2){
            return;
        }
        //校驗?zāi)繕酥?        if(target < 1){
            return;
        }
        //新建哈希表
        Map<Integer,Integer> map = new HashMap<>();
        //數(shù)組長度
        int arrLen = arr.length;
        //遍歷數(shù)組
        for(int i = 0 ; i < arrLen ; i++){
            //計算另一個整數(shù)的期望值
            int otherNum = target - arr[i];
            //去重校驗
            if(map.containsKey(arr[i])){
                System.out.println("Illegal array:the array has duplicate element!");
                return;
            }
            //如果當前期望值符合,則找到答案摔蓝。
            if(map.containsKey(otherNum)){
                System.out.println("答案:value1="+arr[i]+",index1="+i+";value2="+otherNum+",index2="+map.get(otherNum));
            }
            //用哈希表記錄數(shù)據(jù)元素與數(shù)組索引的關(guān)系
            map.put(arr[i],i);
        }
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市贮尉,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌猜谚,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件龄毡,死亡現(xiàn)場離奇詭異,居然都是意外死亡沦零,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進店門路操,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人屯仗,你說我怎么就攤上這事】啵” “怎么了桩撮?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長店量。 經(jīng)常有香客問我,道長融师,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任旱爆,我火速辦了婚禮,結(jié)果婚禮上怀伦,老公的妹妹穿的比我還像新娘。我一直安慰自己空镜,他們只是感情好浩淘,可當我...
    茶點故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布吴攒。 她就那樣靜靜地躺著砂蔽,像睡著了一般洼怔。 火紅的嫁衣襯著肌膚如雪左驾。 梳的紋絲不亂的頭發(fā)上镣隶,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天诡右,我揣著相機與錄音安岂,去河邊找鬼帆吻。 笑死域那,一個胖子當著我的面吹牛猜煮,可吹牛的內(nèi)容都是我干的次员。 我是一名探鬼主播王带,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼愕撰!你這毒婦竟也來了刹衫?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤带迟,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后邮旷,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡婶肩,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了律歼。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡险毁,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出畔况,到底是詐尸還是另有隱情鲸鹦,我是刑警寧澤跷跪,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站吵瞻,受9級特大地震影響葛菇,放射性物質(zhì)發(fā)生泄漏橡羞。R本人自食惡果不足惜眯停,卻給世界環(huán)境...
    茶點故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一卿泽、第九天 我趴在偏房一處隱蔽的房頂上張望莺债。 院中可真熱鬧又厉,春花似錦九府、人聲如沸覆致。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽儡羔。三九已至,卻和暖如春汰蜘,著一層夾襖步出監(jiān)牢的瞬間仇冯,已是汗流浹背族操。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工苛坚, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留色难,地道東北人泼舱。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓枷莉,卻偏偏與公主長得像娇昙,于是被迫代替她去往敵國和親笤妙。 傳聞我的和親對象是個殘疾皇子冒掌,可洞房花燭夜當晚...
    茶點故事閱讀 42,916評論 2 344