并查集 05 基于子集合rank的優(yōu)化

基于 Rank 優(yōu)化的并查集

  • Rank 就是每棵子樹的高度;
  • 在基于 size 的優(yōu)化的并查集中有一個(gè)問題:size 小的子樹的高度并一定就一定小于 size 大的樹,size 大的子樹的高度可能就是 2,size 小的子樹的高度也可能大于 2;
  • 合并時(shí)優(yōu)化的目的是合并后的樹的高度最小壹店,樹的高度越小,查找時(shí)的路勁就越短芝加,速度相應(yīng)也越快硅卢;
  • 因此用表示每棵子樹的高度的數(shù)組 rank 代替表示每棵子樹節(jié)點(diǎn)多少的數(shù)組 sz
public class UnionFind4 implements UF {

    private int[] rank;   // rank[i]表示以i為根的集合所表示的樹的層數(shù)
    private int[] parent; // parent[i]表示第i個(gè)元素所指向的父節(jié)點(diǎn)

    // 構(gòu)造函數(shù)
    public UnionFind4(int size){
        rank = new int[size];
        parent = new int[size];

        // 初始化, 每一個(gè)parent[i]指向自己, 表示每一個(gè)元素自己自成一個(gè)集合
        for( int i = 0 ; i < size ; i ++ ){
            parent[i] = i;
            rank[i] = 1;
        }
    }

    @Override
    public int getSize(){
        return parent.length;
    }

    // 查找過程, 查找元素p所對應(yīng)的集合編號
    // O(h)復(fù)雜度, h為樹的高度
    private int find(int p){
        if(p < 0 || p >= parent.length)
            throw new IllegalArgumentException("p is out of bound.");

        // 不斷去查詢自己的父親節(jié)點(diǎn), 直到到達(dá)根節(jié)點(diǎn)
        // 根節(jié)點(diǎn)的特點(diǎn): parent[p] == p
        while(p != parent[p])
            p = parent[p];
        return p;
    }
    
}

基于 Rank 優(yōu)化后的合并操作

  • 合并的時(shí)候藏杖,哪棵樹的 rank 小将塑,把哪棵樹合并于 rank 大的樹,合并完了不用更新 rank 大的樹的rank 值蝌麸,因?yàn)?rank 小的樹的高度最大比 rank 大的樹的 rank 小 1点寥,合并完了 rank 小的樹的“腳”不會伸出來;
  • 只有兩棵樹的 rank 值相等祥楣,容納另一顆樹的 rank 值需要加 1开财;
// 合并元素p和元素q所屬的集合
// O(h)復(fù)雜度, h為樹的高度
@Override
public void unionElements(int p, int q){
    int pRoot = find(p);
    int qRoot = find(q);

    if( pRoot == qRoot )
        return;

    // 根據(jù)兩個(gè)元素所在樹的rank不同判斷合并方向
    // 將rank低的集合合并到rank高的集合上
    if(rank[pRoot] < rank[qRoot])
        parent[pRoot] = qRoot;
    else if(rank[qRoot] < rank[pRoot])
        parent[qRoot] = pRoot;
    else{ // rank[pRoot] == rank[qRoot]
        parent[pRoot] = qRoot;
        rank[qRoot] += 1;   // 此時(shí), 我維護(hù)rank的值
    }
}

性能比較

import java.util.Random;

public class Main {

    private static double testUF(UF uf, int m){
        int size = uf.getSize();
        Random random = new Random();
        long startTime = System.nanoTime();


        for(int i = 0 ; i < m ; i ++){
            int a = random.nextInt(size);
            int b = random.nextInt(size);
            uf.unionElements(a, b);
        }

        for(int i = 0 ; i < m ; i ++){
            int a = random.nextInt(size);
            int b = random.nextInt(size);
            uf.isConnected(a, b);
        }

        long endTime = System.nanoTime();
        return (endTime - startTime) / 1000000000.0;
    }

    public static void main(String[] args) {
        int size = 10000000;
        int m = 10000000;

        UnionFind3 uf3 = new UnionFind3(size);
        System.out.println("UnionFind3 : " + testUF(uf3, m) + " s");

        UnionFind4 uf4 = new UnionFind4(size);
        System.out.println("UnionFind4 : " + testUF(uf4, m) + " s");
    }
}

輸出:

  • 測試結(jié)果不是很明顯汉柒;
UnionFind3 : 5.7852983 s
UnionFind4 : 5.402423 s
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末误褪,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子碾褂,更是在濱河造成了極大的恐慌兽间,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,427評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件正塌,死亡現(xiàn)場離奇詭異嘀略,居然都是意外死亡恤溶,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,551評論 3 395
  • 文/潘曉璐 我一進(jìn)店門帜羊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來咒程,“玉大人,你說我怎么就攤上這事讼育≌室觯” “怎么了?”我有些...
    開封第一講書人閱讀 165,747評論 0 356
  • 文/不壞的土叔 我叫張陵奶段,是天一觀的道長饥瓷。 經(jīng)常有香客問我,道長痹籍,這世上最難降的妖魔是什么呢铆? 我笑而不...
    開封第一講書人閱讀 58,939評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮蹲缠,結(jié)果婚禮上棺克,老公的妹妹穿的比我還像新娘。我一直安慰自己线定,他們只是感情好逆航,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,955評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著渔肩,像睡著了一般因俐。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上周偎,一...
    開封第一講書人閱讀 51,737評論 1 305
  • 那天抹剩,我揣著相機(jī)與錄音,去河邊找鬼蓉坎。 笑死澳眷,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的蛉艾。 我是一名探鬼主播钳踊,決...
    沈念sama閱讀 40,448評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼勿侯!你這毒婦竟也來了拓瞪?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,352評論 0 276
  • 序言:老撾萬榮一對情侶失蹤助琐,失蹤者是張志新(化名)和其女友劉穎祭埂,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體兵钮,經(jīng)...
    沈念sama閱讀 45,834評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蛆橡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,992評論 3 338
  • 正文 我和宋清朗相戀三年舌界,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片泰演。...
    茶點(diǎn)故事閱讀 40,133評論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡呻拌,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出睦焕,到底是詐尸還是另有隱情柏锄,我是刑警寧澤,帶...
    沈念sama閱讀 35,815評論 5 346
  • 正文 年R本政府宣布复亏,位于F島的核電站趾娃,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏缔御。R本人自食惡果不足惜抬闷,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,477評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望耕突。 院中可真熱鬧笤成,春花似錦、人聲如沸眷茁。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,022評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽上祈。三九已至培遵,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間登刺,已是汗流浹背籽腕。 一陣腳步聲響...
    開封第一講書人閱讀 33,147評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留纸俭,地道東北人皇耗。 一個(gè)月前我還...
    沈念sama閱讀 48,398評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像揍很,于是被迫代替她去往敵國和親郎楼。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,077評論 2 355

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

  • 一些概念 數(shù)據(jù)結(jié)構(gòu)就是研究數(shù)據(jù)的邏輯結(jié)構(gòu)和物理結(jié)構(gòu)以及它們之間相互關(guān)系窒悔,并對這種結(jié)構(gòu)定義相應(yīng)的運(yùn)算呜袁,而且確保經(jīng)過這...
    Winterfell_Z閱讀 5,825評論 0 13
  • 本文主要包括以下內(nèi)容: 并查集的概念 并查集的操作 并查集的實(shí)現(xiàn)和優(yōu)化Quick FindQuick Union基...
    Chiclaim閱讀 1,575評論 1 2
  • 在你進(jìn)入一個(gè)看似穩(wěn)定的平臺之后,一開始是不想動(dòng)(貪圖穩(wěn)定的待遇蛉迹,前幾年不想動(dòng))傅寡,后來是不能動(dòng)(后來發(fā)現(xiàn)放妈,穩(wěn)定的待遇...
    我與乞力馬扎羅閱讀 217評論 0 0
  • 從《我不是藥神》到“疫苗之王”。 電影里還播著珍策,而現(xiàn)實(shí)卻正上演托启。仿佛這是兩個(gè)不相干的世界,在互相平行的軌道攘宙,自顧自...
    斯斯CASS閱讀 388評論 0 1
  • 雷軍有句話屯耸,站在風(fēng)口上連豬都能飛。仔細(xì)去看蹭劈,你就會發(fā)現(xiàn)兩個(gè)問題疗绣。 風(fēng)力要多大? 豬要多重铺韧? 這么一看多矮,風(fēng)太小,豬太...
    王十貳閱讀 155評論 0 0