国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Java高階數(shù)據(jù)結(jié)構(gòu) & 并查集 & 最小生成樹(shù)

這篇具有很好參考價(jià)值的文章主要介紹了Java高階數(shù)據(jù)結(jié)構(gòu) & 并查集 & 最小生成樹(shù)。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

并查集與最小生成樹(shù)

Java高階數(shù)據(jù)結(jié)構(gòu) & 并查集 & 最小生成樹(shù)

Java高階數(shù)據(jù)結(jié)構(gòu) & 并查集 & 最小生成樹(shù)

1. 并查集

1.1 并查集的原理

在一些應(yīng)用問(wèn)題中,我們常常會(huì)遇到一類(lèi)問(wèn)題

一開(kāi)始是一個(gè)人

  1. 后來(lái)新增的人可能與這個(gè)人有關(guān)系,也可能與這個(gè)人無(wú)關(guān)系。
  2. 一個(gè)人與一個(gè)人有關(guān)系,這個(gè)人與另一個(gè)人也有關(guān)系,那么三人都有關(guān)系。
  3. 有關(guān)系的和沒(méi)關(guān)系的之間是不同的類(lèi)別。

Java高階數(shù)據(jù)結(jié)構(gòu) & 并查集 & 最小生成樹(shù)

  • 而隨著人數(shù)增加,有多少類(lèi)別是不確定的,所以用普通的二維數(shù)組是很難描述和存儲(chǔ)這種數(shù)據(jù)結(jié)構(gòu)的。
  • 因?yàn)榧词乖诓豢紤]時(shí)間復(fù)雜度的情況下,我們不知道有多少行,并且出現(xiàn)“三人都有關(guān)系”的情況的時(shí)候,需要合并等等…

而現(xiàn)在有一種數(shù)據(jù)結(jié)構(gòu),就專門(mén)去解決這個(gè)問(wèn)題,這就是 “并查集”

需要將n個(gè)不同的元素劃分成一些不相交的集合。

開(kāi)始時(shí),每個(gè)元素自成一個(gè)單元素集合,然后按一定的規(guī)律將歸于同一組元素的集合合并。

在此過(guò)程中要反復(fù)用到查詢某一個(gè)元素歸屬于那個(gè)集合的運(yùn)算。適合于描述這類(lèi)問(wèn)題的抽象數(shù)據(jù)類(lèi)型稱為并查集(union-find set)

(先說(shuō)怎么存儲(chǔ)表示的,再說(shuō)如何構(gòu)建)

并查集是一個(gè)int型的一維數(shù)組,而本質(zhì)就是一維順序表存儲(chǔ)的“森林”

有如下特性:

  1. 每個(gè)節(jié)點(diǎn)都有對(duì)應(yīng)的下標(biāo),如果有n個(gè)節(jié)點(diǎn),那么他們就對(duì)應(yīng)數(shù)組的0-n-1
  2. 森林的不同的樹(shù),代表不同的類(lèi)別
  3. 每棵樹(shù)都有一個(gè)根節(jié)點(diǎn),這個(gè)根節(jié)點(diǎn)在數(shù)組中的值為負(fù)數(shù),絕對(duì)值為這棵樹(shù)節(jié)點(diǎn)的個(gè)數(shù)
  4. 每棵樹(shù)的非根節(jié)點(diǎn)在數(shù)組中的值為其父節(jié)點(diǎn)在數(shù)組中的下標(biāo)
1.1.1 例子:
  • 現(xiàn)在有十個(gè)人,他們分別代表0 - 9
  • 他們?cè)净ゲ幌嘧R(shí),但是今天是他們因?yàn)榫壏殖霈F(xiàn)在同一輛公交車(chē)上,這次行程他們都很長(zhǎng),并且在路上網(wǎng)絡(luò)全無(wú),他們也毫無(wú)困意,并且都是社牛。

Java高階數(shù)據(jù)結(jié)構(gòu) & 并查集 & 最小生成樹(shù)

  • 他們開(kāi)始與周?chē)能?chē)友交談,可能因?yàn)楦鞣N原因,如興趣愛(ài)好和地域性,他們互相交換了微信。如果兩個(gè)人同時(shí)與一個(gè)人交換微信,那么這兩個(gè)人也會(huì)獲得對(duì)方的微信。
  • 最終下電梯,他們的朋友圈是這樣的:
    Java高階數(shù)據(jù)結(jié)構(gòu) & 并查集 & 最小生成樹(shù)

而并查集將變成這樣:

Java高階數(shù)據(jù)結(jié)構(gòu) & 并查集 & 最小生成樹(shù)

1.1.2 這樣存儲(chǔ)有什么好處呢?

如果有n個(gè)節(jié)點(diǎn),那么一開(kāi)始分為n個(gè)類(lèi)別

如果a0與a1有關(guān)系,那么只需要讓a0和a1其中一棵樹(shù)根節(jié)點(diǎn)接到另一棵樹(shù)的根節(jié)點(diǎn)即可

  1. 一棵樹(shù)的根節(jié)點(diǎn)的值對(duì)于新的樹(shù)的節(jié)點(diǎn)數(shù)的負(fù)數(shù)
  2. 另一棵樹(shù)的根節(jié)點(diǎn)變?yōu)椤靶聵?shù)的非根節(jié)點(diǎn)”,其值為根節(jié)點(diǎn)的下標(biāo)

通過(guò)這個(gè)機(jī)制,最終會(huì)很好的分好類(lèi)別,不需要分好組讓把他們放進(jìn)去,而是他們自己分好了

  • 因?yàn)橥豢脴?shù)的根節(jié)點(diǎn)都一樣,所以負(fù)數(shù)值的元素有多少個(gè),就說(shuō)明有多少組
  • 當(dāng)然所有非根節(jié)點(diǎn)都可以壓縮其值為其所在數(shù)的根節(jié)點(diǎn)對(duì)應(yīng)下標(biāo)

而判斷兩個(gè)節(jié)點(diǎn)有沒(méi)有關(guān)系,就只需要判斷他們根節(jié)點(diǎn)是否相同即可

1.2 并查集的代碼實(shí)現(xiàn)

了解完機(jī)制之后,并查集的代碼實(shí)現(xiàn)并不復(fù)雜!

1.2.1 類(lèi)的定義與屬性
public class UnionFindSet {
    private int[] elem;
}

這就是并查集的主體

1.2.2 構(gòu)造方法
public UnionFindSet(int n) {
    this.elem = new int[n];
    Arrays.fill(this.elem, -1);
}
  • 根據(jù)n構(gòu)造數(shù)組,并且利用fill充滿數(shù)組為-1
1.2.3 獲取下標(biāo)的方法
//根據(jù)需求得到下標(biāo)
public int getIndexByX(int x) {
    return x;
}
  • 這個(gè)需要根據(jù)實(shí)際需求
  • 一般x與i是一致的
    • 或者是x = ki + b(k屬于整數(shù))
    • 對(duì)于其他特殊情況,你需要給每個(gè)節(jié)點(diǎn)安排下標(biāo)
  • 這一點(diǎn)只需要在傳參的時(shí)候轉(zhuǎn)化為下標(biāo)即可

下面的代碼都是認(rèn)為傳參的就是下標(biāo)

1.2.4 獲得根節(jié)點(diǎn)
public int findRoot(int x) {
    if(x < 0) {
        throw new IndexOutOfBoundsException("下標(biāo)為負(fù)數(shù)");
    }
    while(elem[x] >= 0) {
        x = elem[x];
    }
    return x;
}
  • 如果是壓縮后的并查集,直接返回elem[x]即可
  • 如果不是,這需要溯源到根節(jié)點(diǎn)

Java高階數(shù)據(jù)結(jié)構(gòu) & 并查集 & 最小生成樹(shù)

1.2.5 兩個(gè)節(jié)點(diǎn)建立聯(lián)系
  • 只要兩個(gè)節(jié)點(diǎn)來(lái)自不同的樹(shù),那么就可以建立聯(lián)系,即兩個(gè)集合合并
  • 如果來(lái)自同一棵樹(shù),什么也不做

注意:這里你可以選擇x1合并x2,或者x2合并x1

//合并x1和x2
//設(shè)x1任然是根節(jié)點(diǎn),x2連接到x1下
public void union(int x1, int x2) {
    int index1 = findRoot(x1);
    int index2 = findRoot(x2);
    if(index1 == index2) {
        return;//同一棵樹(shù)
    }else {
        elem[index1] += elem[index2];
        elem[index2] = index1;
    }
}

例子:

Java高階數(shù)據(jù)結(jié)構(gòu) & 并查集 & 最小生成樹(shù)

1.2.6 判斷兩個(gè)節(jié)點(diǎn)是否在一個(gè)集合內(nèi)
//判斷是否在一個(gè)集合內(nèi)
public boolean isSameSet(int x1, int x2) {
    return findRoot(x1) == findRoot(x2);
}
1.2.7 計(jì)算集合的個(gè)數(shù)
//計(jì)算集合的個(gè)數(shù)
public int getSetCount() {
    int count = 0;
    for(int x : elem) {
        if(x < 0) {
            count++;
        }
    }
    return count;
}
1.2.8 打印并查集
public void display() {
    for(int x : elem) {
        System.out.print(x + " ");
    }
    System.out.println();
}

1.3 并查集的應(yīng)用

1.3.1 省份的數(shù)量

力扣547

Java高階數(shù)據(jù)結(jié)構(gòu) & 并查集 & 最小生成樹(shù)

是不是一模一樣,^ v ^

分析:

Java高階數(shù)據(jù)結(jié)構(gòu) & 并查集 & 最小生成樹(shù)

代碼:

//獲得省份數(shù)量
public int findCircleNum(int[][] isConnected) {
    int n = isConnected.length;
    UnionFindSet unionFindSet = new UnionFindSet(n);
    for (int i = 0; i < n; i++) {
        for (int j = i + 1; j < n; j++) {
            if(isConnected[i][j] == 1) {
                unionFindSet.union(i, j);
            }
        }
    }
    return unionFindSet.getSetCount();
}

Java高階數(shù)據(jù)結(jié)構(gòu) & 并查集 & 最小生成樹(shù)

1.3.2 等式方程的可滿足性

力扣990

Java高階數(shù)據(jù)結(jié)構(gòu) & 并查集 & 最小生成樹(shù)

分析:

思路:

  1. 區(qū)分不同的字符串種類(lèi)(等于號(hào)類(lèi)和不等號(hào)類(lèi))
  2. 通過(guò)等號(hào)類(lèi)構(gòu)建并查集
  3. 通過(guò)不等號(hào)類(lèi)去檢查是否合理
//下標(biāo)轉(zhuǎn)化方法(這道題節(jié)點(diǎn)最多26個(gè),因?yàn)橹荒苁遣恢貜?fù)的小寫(xiě)字母)
public int getIndexByX(char x) {
    return x - 'a';
}
//等式方程可滿足性

public boolean equationsPossible(String[] equations) {
    UnionFindSet unionFindSet = new UnionFindSet(26);
    for(String str : equations) {
        if(str.charAt(1) == '=') {
            char ch1 = str.charAt(0);
            char ch2 = str.charAt(3);
            unionFindSet.union(getIndexByX(ch1), getIndexByX(ch2));
        }
    }
    for(String str : equations) {
        if(str.charAt(1) == '!') {
            char ch1 = str.charAt(0);
            char ch2 = str.charAt(3);
            if(unionFindSet.isSameSet(getIndexByX(ch1), getIndexByX(ch2))) {
                return false;
            }
        }
    }
    return true;
}

Java高階數(shù)據(jù)結(jié)構(gòu) & 并查集 & 最小生成樹(shù)

1.3.3 Kruskal算法獲取圖的最小生成樹(shù)

這也是接下來(lái)要講的

2. 圖的最小生成樹(shù)問(wèn)題

對(duì)于圖的基本知識(shí),請(qǐng)參考博客:Java高階數(shù)據(jù)結(jié)構(gòu) & 圖 & 圖的表示與遍歷_s:103的博客-CSDN博客

下面不作贅述~

2.1 生成樹(shù)是什么

連通圖中的每一棵生成樹(shù),都是原圖的一個(gè)極大無(wú)環(huán)子圖,即:從其中刪去任何一條邊,生成樹(shù) 就不在連 通;反之,在其中引入任何一條新邊,都會(huì)形成一條回路。

連通圖n個(gè)頂點(diǎn)組成,則其生成樹(shù)必含n個(gè)頂點(diǎn)和n-1條邊。因此構(gòu)造最小生成樹(shù)的準(zhǔn)則有五 條:

  1. 只能由圖中的邊來(lái)構(gòu)造最小生成樹(shù)
  2. 只能使用恰好n-1條邊來(lái)連接圖中的n個(gè)頂點(diǎn)
  3. 選用的n-1條邊不能構(gòu)成回路
    • 當(dāng)然,都滿足第2條,就一定不會(huì)構(gòu)成回路
  4. n-1條邊的權(quán)和最小
  5. 是連通圖
    • 只有連通無(wú)向圖存在生成樹(shù)

當(dāng)然,最小生成樹(shù),可能不止一棵

2.2 獲取最小生成樹(shù)算法

貪心算法: 是指在問(wèn)題求解時(shí),總是做出當(dāng)前看起來(lái)最好的選擇。也就是說(shuō)貪心算法做出的不是整體 最優(yōu)的 的選擇,而是某種意義上的局部最優(yōu)解。貪心算法不是對(duì)所有的問(wèn)題都能得到整體最優(yōu)解。

以下兩種算法的本質(zhì)都是貪心算法,雖然數(shù)學(xué)上不嚴(yán)謹(jǐn),卻能很好的解決這個(gè)問(wèn)題~

  • 不需要糾結(jié),用就是了
2.2.1 Kruskal算法
  • 克魯斯卡爾算法是全局的貪心算法

步驟:

  1. 選取全局中最短的邊,并標(biāo)記兩個(gè)頂點(diǎn)
  2. 選取全局中未被標(biāo)記的邊(兩個(gè)端點(diǎn)都未被標(biāo)記)
    • 如果幾個(gè)一樣小的,沒(méi)關(guān)系,用哪個(gè)都o(jì)k
    • 這也是為什么最小生成樹(shù)可能不唯一的原因
  3. 以此類(lèi)推…
  4. 在標(biāo)價(jià)前要判斷標(biāo)記后是否成環(huán),如果是,取消此次選擇
  5. 直到選出n-1條邊,此時(shí)計(jì)算結(jié)束

例子:

  • 求一棵如下圖的最小生成樹(shù)

Java高階數(shù)據(jù)結(jié)構(gòu) & 并查集 & 最小生成樹(shù)

步驟如下:

Java高階數(shù)據(jù)結(jié)構(gòu) & 并查集 & 最小生成樹(shù)

2.2.2 Prime算法
  • 普利姆算法的本質(zhì)是局部的貪心算法

步驟:

  1. 確定并標(biāo)記一個(gè)起始節(jié)點(diǎn),后續(xù)樹(shù)的生長(zhǎng)以此為基礎(chǔ)
  2. 生長(zhǎng):在此節(jié)點(diǎn)能直接連通的所有節(jié)點(diǎn)中,選擇一條權(quán)最小的邊,并標(biāo)記該節(jié)點(diǎn)
  3. 繼續(xù)生長(zhǎng):在樹(shù)的所有節(jié)點(diǎn)能直接連通的所有節(jié)點(diǎn)中,選擇一條權(quán)最小的邊,并標(biāo)記該節(jié)點(diǎn)
    • 不能連通被標(biāo)記的節(jié)點(diǎn)
    • 無(wú)向連通圖不會(huì)出現(xiàn)選不出來(lái)的情況
  4. 直到所有節(jié)點(diǎn)都被標(biāo)記則結(jié)束,已生長(zhǎng)成最小生成樹(shù)
    • 或者是獲得了n-1條邊,不成環(huán)則一定有n個(gè)節(jié)點(diǎn)

例子:

  • 求一棵如下圖以a的起始節(jié)點(diǎn)的最小生成樹(shù)

Java高階數(shù)據(jù)結(jié)構(gòu) & 并查集 & 最小生成樹(shù)

步驟:

Java高階數(shù)據(jù)結(jié)構(gòu) & 并查集 & 最小生成樹(shù)

可見(jiàn),不同算法求出來(lái)的最小生成樹(shù)不同

2.3 獲取最小生成樹(shù)代碼實(shí)現(xiàn)

通過(guò)剛才的算法講解,其實(shí)思路不難,現(xiàn)在要解決的主要是算法轉(zhuǎn)化為代碼~

2.3.1 Kruskal算法代碼實(shí)現(xiàn)(鄰接矩陣)

待處理的問(wèn)題:

  1. 怎么獲得全場(chǎng)最短的邊?
  2. 怎么保證不會(huì)成環(huán)

解決:

  1. 優(yōu)先級(jí)隊(duì)列 去存儲(chǔ)所有的邊,每次都取小根堆堆頂,這樣可以高效的獲取最小邊
    • 由于是全局的,所以不存在 “局部最小問(wèn)題”
  2. 并查集 去整理節(jié)點(diǎn)之間的關(guān)系,如果一條邊的兩個(gè)節(jié)點(diǎn)是有關(guān)系(已在同一個(gè)圖)的,就不能取

代碼實(shí)現(xiàn):

  1. Edge類(lèi)的定義
static class Edge {
    int src;
    int dest;
    int weight;

    public Edge(int src, int dest, int weight) {
        this.src = src;
        this.dest = dest;
        this.weight = weight;
    }
}
  1. 導(dǎo)入并查集這個(gè)類(lèi)(剛才實(shí)現(xiàn)的)

Java高階數(shù)據(jù)結(jié)構(gòu) & 并查集 & 最小生成樹(shù)

  • 技巧:把代碼復(fù)制直接粘貼就行了
    • 這樣會(huì)自動(dòng)根據(jù)public類(lèi)構(gòu)建java文件

Java高階數(shù)據(jù)結(jié)構(gòu) & 并查集 & 最小生成樹(shù)

  1. 庫(kù)魯斯卡爾算法對(duì)應(yīng)方法
/**
 *
 * @param minTree 最小生成樹(shù)放在圖 minTree中
 * @return 最小生成樹(shù)的權(quán)和
 */
public int kruskal(GraphByMatrix minTree) {
    //1. 優(yōu)先級(jí)序列存放所有邊
    PriorityQueue<Edge> minHeap = new PriorityQueue<Edge>(
            (o1, o2) -> {
                return o1.weight - o2.weight;
            }
    );
    int n = matrix.length;
    //無(wú)向圖只需要一條即可
    for (int i = 0; i < n; i++) {
        for (int j = i + 1; j < n; j++) {
            minHeap.offer(new Edge(i, j, matrix[i][j]));
        }
    }
    //最終的權(quán)值和
    int retWeight = 0;
    //定義并查集
    UnionFindSet unionFindSet = new UnionFindSet(n);
    int size = 0;//已選邊的條數(shù)
    //選取n-1條邊,如果不成環(huán),必然選中n個(gè)節(jié)點(diǎn),
    // 如果隊(duì)列都空了,都沒(méi)有n-1條邊,則不是無(wú)向連通圖
    while(size < n - 1 && !minHeap.isEmpty()) {
        Edge minEdge = minHeap.poll();
        int src = minEdge.src;
        int dest = minEdge.dest;
        //如果src與dest師出同門(mén),不能添加
        if(!unionFindSet.isSameSet(src, dest)) {
            System.out.println(arrayV[src] +"--- "
                    +arrayV[dest]+" : "+matrix[src][dest]);
            //這兩個(gè)節(jié)點(diǎn)建立關(guān)系
            unionFindSet.union(src, dest);
            //存放在minTree圖中,最小生成樹(shù)返回到這里面
            minTree.addEdge(arrayV[src], arrayV[dest], minEdge.weight);
            //權(quán)值和
            retWeight += minEdge.weight;
            //被選中的邊的條數(shù)加一
            size++;
        }
    }
    return size == n - 1 ? retWeight : Integer.MAX_VALUE;
}

測(cè)試:

  • 建立圖對(duì)象(跟上面的圖解一致)
  • 打印最小生成樹(shù)權(quán)和以及最小生成樹(shù)的鄰接矩陣
public static void testGraphMinTree1() {
    String str = "abcdefghi";
    char[] array =str.toCharArray();
    GraphByMatrix g = new GraphByMatrix(str.length(),false);
    g.initArrayV(array);
    g.addEdge('a', 'b', 4);
    g.addEdge('a', 'h', 8);
    //g.addEdge('a', 'h', 9);
    g.addEdge('b', 'c', 8);
    g.addEdge('b', 'h', 11);
    g.addEdge('c', 'i', 2);
    g.addEdge('c', 'f', 4);
    g.addEdge('c', 'd', 7);
    g.addEdge('d', 'f', 14);
    g.addEdge('d', 'e', 9);
    g.addEdge('e', 'f', 10);
    g.addEdge('f', 'g', 2);
    g.addEdge('g', 'h', 1);
    g.addEdge('g', 'i', 6);
    g.addEdge('h', 'i', 7);
    GraphByMatrix kminTree = new GraphByMatrix(str.length(),false);
    kminTree.initArrayV(array);
    System.out.println(g.kruskal(kminTree));
    kminTree.printGraph();
}

public static void main(String[] args) {
    testGraphMinTree1();
}

Java高階數(shù)據(jù)結(jié)構(gòu) & 并查集 & 最小生成樹(shù)

2.3.2 Prime算法代碼實(shí)現(xiàn)(鄰接矩陣)

待處理問(wèn)題:

  1. 怎么找到一條當(dāng)前標(biāo)記節(jié)點(diǎn)指向未標(biāo)記節(jié)點(diǎn)的邊
  2. 這條邊怎么保證是最小的

解決:

  1. 由于這種算法明顯分為了兩種關(guān)系:被標(biāo)記與未被標(biāo)記

    • 所以直接創(chuàng)建兩個(gè)集合(HashSet)即可,不需要用到并查集
    • 如果指向的頂點(diǎn)屬于被標(biāo)記過(guò),則不能選擇它
    • 選擇后目的頂點(diǎn)被標(biāo)記,也讓這條邊不會(huì)再次被選中
  2. 一樣可以用 優(yōu)先級(jí)隊(duì)列

    • 每次一個(gè)頂點(diǎn)被標(biāo)記的時(shí)候,都需要將這個(gè)頂點(diǎn)連接的所有邊加入隊(duì)列中

    • 重復(fù)的有很多,但是由于剛才的機(jī)制,不會(huì)出現(xiàn)成環(huán)的現(xiàn)象

    • 在這里隊(duì)列是需要?jiǎng)討B(tài)更新的,每次都為了找到“局部最小

代碼實(shí)現(xiàn):

  • 普利姆算法對(duì)應(yīng)方法
public int prime(GraphByMatrix minTree, char V) {
    //獲取頂點(diǎn)的下標(biāo)
    int srcIndex = getIndexOfV(V);

    //起始節(jié)點(diǎn)集合與目的節(jié)點(diǎn)集合
    Set<Integer> srcSet = new HashSet<>();
    Set<Integer> destSet = new HashSet<>();

    //初始化兩個(gè)集合
    srcSet.add(srcIndex);
    int n = matrix.length;
    for (int i = 0; i < n; i++) {
        if(i != srcIndex) {
            destSet.add(i);
        }
    }

    //從srcSet到destSet集合的邊
    //定義優(yōu)先級(jí)隊(duì)列與初始化優(yōu)先級(jí)隊(duì)列
    PriorityQueue<Edge> minHeap = new PriorityQueue<>(
            (o1, o2) -> {
                return o1.weight - o2.weight;
                //左大于右為正,為升序小根堆
            }
    );
    for (int i = 0; i < n; i++) {
        if(matrix[srcIndex][i] != Integer.MAX_VALUE) {
            minHeap.offer(new Edge(srcIndex, i, matrix[srcIndex][i]));
        }
    }

    int retWeight = 0;//返回的權(quán)值和
    int edgeCount = 0;//已選中的邊

    //核心循環(huán)
    while(edgeCount < n - 1 && !minHeap.isEmpty()) {
        Edge minEdge = minHeap.poll();
        int src = minEdge.src;
        int dest = minEdge.dest;
        //判斷dest是否被標(biāo)記
        if(!srcSet.contains(dest)) {
            minTree.addEdge(arrayV[src], arrayV[dest], matrix[src][dest]);
            System.out.println(arrayV[src] + "---" + arrayV[dest] + " : "
            + matrix[src][dest]);
            edgeCount++;
            retWeight += matrix[src][dest];
            
            //目的節(jié)點(diǎn)被標(biāo)記:加入srcSet,在destSet除名
            srcSet.add(dest);
            destSet.remove(dest);
            
            //添加新增起始頂點(diǎn)的所有直接連通的邊
            for (int i = 0; i < n; i++) {
                //多重保證,安心!
                if(matrix[dest][i] != Integer.MAX_VALUE && destSet.contains(i)) {
                    minHeap.offer(new Edge(dest, i, matrix[dest][i]));
                }
            }
        }
    }
    return edgeCount == n - 1 ? retWeight : Integer.MAX_VALUE;
}

測(cè)試:

  • 同上,只是把方法換成prime,并給定起始頂點(diǎn)
public static void testGraphMinTree2() {
    String str = "abcdefghi";
    char[] array =str.toCharArray();
    GraphByMatrix g = new GraphByMatrix(str.length(),false);
    g.initArrayV(array);
    g.addEdge('a', 'b', 4);
    g.addEdge('a', 'h', 8);
    //g.addEdge('a', 'h', 9);
    g.addEdge('b', 'c', 8);
    g.addEdge('b', 'h', 11);
    g.addEdge('c', 'i', 2);
    g.addEdge('c', 'f', 4);
    g.addEdge('c', 'd', 7);
    g.addEdge('d', 'f', 14);
    g.addEdge('d', 'e', 9);
    g.addEdge('e', 'f', 10);
    g.addEdge('f', 'g', 2);
    g.addEdge('g', 'h', 1);
    g.addEdge('g', 'i', 6);
    g.addEdge('h', 'i', 7);
    GraphByMatrix kminTree = new GraphByMatrix(str.length(),false);
    kminTree.initArrayV(array);
    System.out.println(g.prime(kminTree, 'a'));
    kminTree.printGraph();
}

public static void main(String[] args) {
    testGraphMinTree2();
}

Java高階數(shù)據(jù)結(jié)構(gòu) & 并查集 & 最小生成樹(shù)

這兩個(gè)算法的代碼可能比較難理解,你可以結(jié)合上面的圖片和文字講解去理解代碼!


文章到此結(jié)束!謝謝觀看
可以叫我 小馬,我可能寫(xiě)的不好或者有錯(cuò)誤,但是一起加油鴨??

后續(xù)更新圖的最短路徑問(wèn)題和拓?fù)渑判?,敬?qǐng)期待!文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-436892.html


到了這里,關(guān)于Java高階數(shù)據(jù)結(jié)構(gòu) & 并查集 & 最小生成樹(shù)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 數(shù)據(jù)結(jié)構(gòu)--并查集

    數(shù)據(jù)結(jié)構(gòu)--并查集

    所有元素的全集s 將各個(gè)元素劃分為若干個(gè)互不相交的子集 用一個(gè)數(shù)組S[ ]即可表示“集合”關(guān)系 集合的兩個(gè)基本操作―— “并” color{red}“并” “ 并 ” 和 “查” color{red}“查” “ 查 ” Find -—“查”操作:確定一個(gè)指定元素所屬集合 Union --“并”操作:將兩個(gè)不想交的集

    2024年02月15日
    瀏覽(17)
  • 【數(shù)據(jù)結(jié)構(gòu)】并查集

    【數(shù)據(jù)結(jié)構(gòu)】并查集

    并查集是簡(jiǎn)單的數(shù)據(jù)結(jié)構(gòu),學(xué)會(huì)并查集,為圖打好基礎(chǔ)。 是樹(shù)狀的數(shù)據(jù)結(jié)構(gòu),用于處理相交集合的合并與查詢 通常用森林表示,一片森林表示一個(gè)集合 并查集一般需要完成 查找元素屬于哪個(gè)集合 查看兩個(gè)元素是否屬于同一個(gè)集合 將兩個(gè)集合歸并成一個(gè)集合 集合的個(gè)數(shù) 假

    2024年02月19日
    瀏覽(17)
  • 【數(shù)據(jù)結(jié)構(gòu)與算法】并查集

    【數(shù)據(jù)結(jié)構(gòu)與算法】并查集

    并查集是一個(gè)樹(shù)形結(jié)構(gòu),所謂的并查,就是 當(dāng)我們有了一個(gè)節(jié)點(diǎn),我們就能知道這個(gè)節(jié)點(diǎn)屬于哪個(gè)集合 。 舉個(gè)例子理解以下:戰(zhàn)國(guó)時(shí)期有很多國(guó)家,它們會(huì)互相打仗,那么現(xiàn)在有兩個(gè)互相不認(rèn)識(shí)的人,如何知道對(duì)方是敵是友呢? 現(xiàn)在有一種方法:每個(gè)國(guó)家都有一個(gè)大王,我

    2023年04月15日
    瀏覽(20)
  • 數(shù)據(jù)結(jié)構(gòu)之并查集

    數(shù)據(jù)結(jié)構(gòu)之并查集

    并查表原理是一種 樹(shù)型的數(shù)據(jù)結(jié)構(gòu) ,用于處理一些不相交集合的合并及查詢問(wèn)題。并查集的思想是用一個(gè)數(shù)組表示了整片森林(parent),樹(shù)的根節(jié)點(diǎn)唯一標(biāo)識(shí)了一個(gè)集合,我們只要找到了某個(gè)元素的樹(shù)根,就能確定它在哪個(gè)集合里。這類(lèi)問(wèn)題的抽象數(shù)據(jù)類(lèi)型稱為并查集(uni

    2024年02月12日
    瀏覽(20)
  • 數(shù)據(jù)結(jié)構(gòu)詳細(xì)筆記——并查集

    集合:將各個(gè)元素劃分為若干個(gè)互不相交的子集的集合 森林是m(m=0)棵互不相交的樹(shù)的集合 優(yōu)化思路:在每次Union操作構(gòu)建樹(shù)的時(shí)候,盡可能讓樹(shù)不長(zhǎng)高 ①用根結(jié)點(diǎn)的絕對(duì)值表示樹(shù)的結(jié)點(diǎn)的總數(shù) ②Union操作,讓小樹(shù)合并到大樹(shù) 優(yōu)化思路:先找到根結(jié)點(diǎn),再將查找路徑上所有結(jié)

    2024年02月06日
    瀏覽(16)
  • 算法與數(shù)據(jù)結(jié)構(gòu)(九)--并查集

    算法與數(shù)據(jù)結(jié)構(gòu)(九)--并查集

    1.處理對(duì)象:Disjoint Set,即“不相交集合”。 在一些應(yīng)用問(wèn)題中,需將n個(gè)不同的元素劃分成一組不相交的集合。開(kāi)始時(shí),每個(gè)元素自成一個(gè)單元素集合,然后按一定順序?qū)儆谕唤M元素的集合合并。其間要反復(fù)用到查詢某個(gè)元素屬于哪個(gè)集合的運(yùn)算。適合于描述這類(lèi)問(wèn)題的

    2024年02月10日
    瀏覽(29)
  • 【數(shù)據(jù)結(jié)構(gòu)】| 并查集及其優(yōu)化實(shí)現(xiàn)

    【數(shù)據(jù)結(jié)構(gòu)】| 并查集及其優(yōu)化實(shí)現(xiàn)

    以一個(gè)直觀的問(wèn)題來(lái)引入并查集的概念。 親戚問(wèn)題:有一群人,他們屬于不同家族,同一個(gè)家族里的人互為親戚,不同家族的人不是親戚。隨機(jī)指定兩個(gè)人,問(wèn)他們是否有親戚關(guān)系。 以下圖3個(gè)不相交的集合表示 3 個(gè)家族,當(dāng)詢問(wèn)兩個(gè)人是否有親戚關(guān)系時(shí),也就是問(wèn)兩個(gè)元素

    2024年02月09日
    瀏覽(18)
  • 計(jì)算機(jī)基礎(chǔ)--->數(shù)據(jù)結(jié)構(gòu)(9)【并查集】

    計(jì)算機(jī)基礎(chǔ)--->數(shù)據(jù)結(jié)構(gòu)(9)【并查集】

    并查集是一種用于解決集合合并和查詢問(wèn)題的數(shù)據(jù)結(jié)構(gòu),主要用于實(shí)現(xiàn)有關(guān)集合的操作,它有兩種主要操作,合并(union)和查找(find)。 查找(Find):用來(lái)確定元素屬于哪個(gè)集合。它接受一個(gè)元素作為參數(shù),并返回這個(gè)元素所屬集合的代表元素。通過(guò)查找操作,可以判斷

    2024年02月15日
    瀏覽(30)
  • 數(shù)據(jù)結(jié)構(gòu)(八):并查集詳解 (多圖+動(dòng)圖)

    數(shù)據(jù)結(jié)構(gòu)(八):并查集詳解 (多圖+動(dòng)圖)

    目錄 一、什么是并查集 二、并查集的存儲(chǔ)結(jié)構(gòu) 三、并查集的基本操作 (一)初始化 (二)Find操作 (三)Union操作 四、并查集的優(yōu)化 (一)Union操作優(yōu)化(小樹(shù)并入大樹(shù)) (二)Find操作優(yōu)化(壓縮路徑) ????????并查集的邏輯結(jié)構(gòu)是一個(gè)包含N個(gè)元素的 集合 ,如圖:

    2024年02月03日
    瀏覽(19)
  • 數(shù)據(jù)結(jié)構(gòu)--并查集的進(jìn)一步優(yōu)化

    數(shù)據(jù)結(jié)構(gòu)--并查集的進(jìn)一步優(yōu)化

    壓縮路徑 ? ? F i n d 操作,先找到根節(jié)點(diǎn),再將查找路徑上所有結(jié)點(diǎn)都掛到根結(jié)點(diǎn)下 color{red}壓縮路徑 -- Find操作,先找到根節(jié)點(diǎn),再將查找路徑上所有結(jié)點(diǎn)都掛到根結(jié)點(diǎn)下 壓縮路徑 ? ? F in d 操作,先找到根節(jié)點(diǎn),再將查找路徑上所有結(jié)點(diǎn)都掛到根結(jié)點(diǎn)下 每次Find操作,

    2024年02月15日
    瀏覽(26)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包