散列表

如果所有的鍵都是小整數(shù)己单,我們可以用一個數(shù)組來實現(xiàn)無序的符號表唉窃,將鍵作為數(shù)組的索引而數(shù)組中鍵i處存儲對應(yīng)的值。這樣我們就可以快速訪問任意鍵的值纹笼。
散列表就是這種簡易方法的擴(kuò)展纹份,并能夠處理更加復(fù)雜的類型的鍵,我們需要通過算術(shù)操作將鍵轉(zhuǎn)化為數(shù)組的索引來訪問數(shù)組中的鍵值對廷痘。
使用散列表的查找算法分為兩步蔓涧。第一步是用散列函數(shù)將被查找的鍵轉(zhuǎn)化為數(shù)組的一個索引;第二步是就是一個處理碰撞沖突的過程笋额。


  • 散列函數(shù)
    Java中每種數(shù)據(jù)類型都繼承了一個能夠返回32比特整數(shù)的hashCode()方法元暴,與除留余數(shù)法結(jié)合產(chǎn)生一個0到M-1的整數(shù):

    private int hash(Key x){
        return (x.hashCode() && 0x7fffffff) % M;
    }
    
  • 基于拉鏈法的散列表
    散列函數(shù)能將鍵轉(zhuǎn)化為數(shù)組索引,而散列算法的第二步是處理碰撞兄猩,也就是兩個或多個散列值相同的情況茉盏。拉鏈法將大小為M的每個元素均指向一條鏈表,鏈表中的每個結(jié)點均存儲了散列值為該元素索引的鍵值對枢冤。這個方法的基本思想是選取盡可能大的M以使得所有鏈都盡可能的短鸠姨。
    public class SeparateChainingHashST<Key, Value>{
    private int N; //鍵值對總數(shù)
    private int M; //散列表大小
    private SequentialSearchST<Key, Value>[] st; //存放鏈接的對象數(shù)組
    public SeparateChainingHashST(){
    this(997);
    }
    public SeparateChainingHashST(int M){
    //創(chuàng)建M條鏈表
    this.M = M;
    st = (SequentialSearchST<Key, Value>[]) new SequentialSearchST[M];
    for (int i=0; i<M; i++)
    st[i] = new SequentialSearchST();
    }
    private int hash(Key key){
    return ( key.hashCode() & 0x7fffffff) %M;
    }
    public Value get(Key key){
    return (Value) st[hash(key)].get(key);
    public void put(Key key, Value val){
    st[hash(key)].put(key, val);
    }
    public Iterable<Key> keys()

  • 基于線性探測法的散列表
    實現(xiàn)散列表的另一種方式是用大小為M的數(shù)組來存儲N個鍵值對,其中M>N淹真。依靠數(shù)組中的空位來解決碰撞沖突讶迁。基于這種策略的所有方法被稱為開放地址散列表核蘸。
    開放地址散列表實現(xiàn)的最簡單方法是線性探測法——當(dāng)碰撞發(fā)生時巍糯,我們直接檢測下一個位置,于是產(chǎn)生三種結(jié)果:

    • 命中值纱,該位置的鍵和被查找的鍵相同鳞贷;
    • 未命中,鍵為空虐唠;
    • 繼續(xù)查找搀愧,該位置的鍵與被查找的鍵不同。

    開放地址類的散列表的核心思想是與其將內(nèi)存用作鏈表疆偿,不如將它們作為散列表的空元素咱筛。

    public class LinearProbingHashST<Key, Value>{
        private int N;
        private int M;
        private Key[] keys;
        private Value[] vals;
        public LinearProbingHashST(){
            keys = (Key[]) new Object[M];
            vals = (Value[]) new Object[M];
        }
        private int hash(Key key){
            return (key.hashCode() & 0x7fffffff ) %M;
        }
        private resize();
        public void put(Key key, Value val){
            if( N >= M/2) resize(2*M);
            int i;
            for( i =hash(key); keys[i] ! = null; i = (i+1)%M){
                if( keys[i].equals(key)){
                    vals[i] = val;
                    return;
                }
                keys[i] = key;
                vals[i] = val;
                N++;
        }
    
        public Value get(Key key){
            for( int i = hash(key); keys[i] != null; i = (i+1)%M)
                if(keys[i].equals(key))
                    return vals[i];
            return null;
        }
    }
    

對于線性探測法的刪除操作,直接將該鍵的位置設(shè)置為null是不行的杆故,因為這樣將會導(dǎo)致該鍵位置之后的元素都無法被找到迅箩。
public void delete(Key key){
if( !contains(key)) return;
int i = hash(key);
while(!key.equals(keys[i]))
i = (i+1) % M;
keys[i] = null;
vals[i] = null;
i = (i+1) % M;
while( keys[i] != null){
Key keyToRedo = keys[i];
Value valToRedo = vals[i];
keys[i] = null;
vals[i] = null;
N--;
put(keyToRedo, valToRedo);
i = (i+1) % M;
}
N--;
if( N>0 && N <= M/8) resize(M/2);
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市处铛,隨后出現(xiàn)的幾起案子饲趋,更是在濱河造成了極大的恐慌拐揭,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,110評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件奕塑,死亡現(xiàn)場離奇詭異堂污,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)龄砰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,443評論 3 395
  • 文/潘曉璐 我一進(jìn)店門盟猖,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人换棚,你說我怎么就攤上這事式镐。” “怎么了固蚤?”我有些...
    開封第一講書人閱讀 165,474評論 0 356
  • 文/不壞的土叔 我叫張陵娘汞,是天一觀的道長。 經(jīng)常有香客問我颇蜡,道長价说,這世上最難降的妖魔是什么辆亏? 我笑而不...
    開封第一講書人閱讀 58,881評論 1 295
  • 正文 為了忘掉前任风秤,我火速辦了婚禮,結(jié)果婚禮上扮叨,老公的妹妹穿的比我還像新娘缤弦。我一直安慰自己,他們只是感情好彻磁,可當(dāng)我...
    茶點故事閱讀 67,902評論 6 392
  • 文/花漫 我一把揭開白布碍沐。 她就那樣靜靜地躺著,像睡著了一般衷蜓。 火紅的嫁衣襯著肌膚如雪累提。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,698評論 1 305
  • 那天磁浇,我揣著相機(jī)與錄音斋陪,去河邊找鬼。 笑死置吓,一個胖子當(dāng)著我的面吹牛无虚,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播衍锚,決...
    沈念sama閱讀 40,418評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼友题,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了戴质?” 一聲冷哼從身側(cè)響起度宦,我...
    開封第一講書人閱讀 39,332評論 0 276
  • 序言:老撾萬榮一對情侶失蹤踢匣,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后戈抄,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體符糊,經(jīng)...
    沈念sama閱讀 45,796評論 1 316
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,968評論 3 337
  • 正文 我和宋清朗相戀三年呛凶,在試婚紗的時候發(fā)現(xiàn)自己被綠了男娄。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,110評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡漾稀,死狀恐怖模闲,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情崭捍,我是刑警寧澤尸折,帶...
    沈念sama閱讀 35,792評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站殷蛇,受9級特大地震影響实夹,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜粒梦,卻給世界環(huán)境...
    茶點故事閱讀 41,455評論 3 331
  • 文/蒙蒙 一亮航、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧匀们,春花似錦缴淋、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,003評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至祖灰,卻和暖如春钟沛,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背局扶。 一陣腳步聲響...
    開封第一講書人閱讀 33,130評論 1 272
  • 我被黑心中介騙來泰國打工恨统, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人详民。 一個月前我還...
    沈念sama閱讀 48,348評論 3 373
  • 正文 我出身青樓延欠,卻偏偏與公主長得像,于是被迫代替她去往敵國和親沈跨。 傳聞我的和親對象是個殘疾皇子由捎,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,047評論 2 355

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)饿凛,斷路器狞玛,智...
    卡卡羅2017閱讀 134,662評論 18 139
  • 本文主要介紹散列表(Hash Table)這一常見數(shù)據(jù)結(jié)構(gòu)的原理與實現(xiàn)软驰。由于個人水平有限,文章中難免存在不準(zhǔn)確或是...
    absfree閱讀 16,321評論 2 35
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法心肪,類相關(guān)的語法锭亏,內(nèi)部類的語法,繼承相關(guān)的語法硬鞍,異常的語法慧瘤,線程的語...
    子非魚_t_閱讀 31,639評論 18 399
  • 數(shù)據(jù)結(jié)構(gòu)與算法--散列表 之前學(xué)習(xí)了基于鏈表的順序查找、基于有序數(shù)組的二分查找固该、二叉查找樹锅减、紅黑樹,這些算法在查找...
    sunhaiyu閱讀 653評論 3 5
  • 劍一直都是東西方文明中地位比較高的武器伐坏。在中國古代怔匣,劍被稱作“百兵之君”。武術(shù)中有“百日刀桦沉,千日槍每瞒,萬日劍”的說法...
    兩只筷子湊一雙閱讀 687評論 0 2