欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java實現(xiàn)拓撲排序算法的示例代碼

 更新時間:2022年07月18日 09:44:15   作者:chengqiuming  
在圖論中,拓撲排序(Topological Sorting)是一個有向無環(huán)圖(DAG, Directed Acyclic Graph)的所有頂點的線性序列。本文將為大家講講拓撲排序算法的原理及實現(xiàn),需要的可以參考一下

拓撲排序原理

1.點睛

一個無環(huán)的有向圖被稱為有向無環(huán)圖。有向無環(huán)圖是描述一個工程、計劃、生產(chǎn)、系統(tǒng)等流程的有效工具。一個大工程可分為若干子工程(活動),活動之間通常有一定的約束,例如先做什么活動,有什么活動完成后才可以開始下一個活動。

用節(jié)點表示活動,用弧表示活動之間的優(yōu)先關(guān)系的有向圖,被稱為 AOV 網(wǎng)。

在 AOV 網(wǎng)中,若從節(jié)點 i 到節(jié)點 j 存在一條有向路徑,則稱節(jié)點 i 是節(jié)點 j 的前驅(qū),或者稱節(jié)點 j 是節(jié)點 i 的后繼。若<i,j>是圖中的弧,則稱節(jié)點 i 是節(jié)點 j 的直接前驅(qū),節(jié)點 j 是節(jié)點 i 的直接后繼。

在 AOV 網(wǎng)中弧表示了活動之間存在的制約關(guān)系。例如,計算機專業(yè)的學生必須完成一系列規(guī)定的基礎(chǔ)課和專業(yè)課才能畢業(yè)。學生按照怎樣的順序來學習這些課程呢?

課程的名稱與相應編號如下表所示。

課程編號課程名稱先修課程
C程序設(shè)計基礎(chǔ)
C1數(shù)據(jù)結(jié)構(gòu)C0、C2
C2離散數(shù)學C0
C3高級程序設(shè)計C0、C
C4數(shù)值分析C2、C3、C5
C5高等數(shù)學

如果用節(jié)點表示課程,用弧表示先修關(guān)系,若課程 i 是課程 j 的先修課程,則用弧<i,j>表示,課程之間的關(guān)系如下圖所示。

在 AOV 中不允許有環(huán),否則會出現(xiàn)自己是自己的前驅(qū)情況,陷入死循環(huán)。怎么判斷在 AOV 網(wǎng)中是否有環(huán)呢?一種檢測的辦法就是對有向圖中的節(jié)點進行拓撲排序。如果 AOV 網(wǎng)中的所有節(jié)點都在拓撲序列中,則在 AOV 網(wǎng)中必定無環(huán)。

2.拓撲排序

拓撲排序指將 AOV 網(wǎng)中的節(jié)點排成一個線性序列,該序列必須滿足:若從節(jié)點 i 到節(jié)點 j 有一條路徑,則在該序列中節(jié)點 i 一定在節(jié)點 j 之前。

拓撲排序的基本思想:

1 選擇一個無前驅(qū)的節(jié)點并輸出。

2 從圖中刪除該節(jié)點和該節(jié)點所有發(fā)出邊。

3 重復步驟1、2,直到不存在無前驅(qū)的節(jié)點。

4 如果輸出的節(jié)點數(shù)少于 AOV 網(wǎng)中節(jié)點數(shù),則說網(wǎng)中有環(huán),否則輸出的序列即拓撲序列。

拓撲排序并不是唯一的,例如上圖中,節(jié)點 C0 和 C5 都無前驅(qū),先輸出哪一個都可以。

下面圖解是其中一種刪除順序。

拓撲序列為:C0、C5、C3、C2、C1、C4

在上述過程中有刪除節(jié)點和邊的操作,實際上,沒必要真的刪除節(jié)點和邊??梢詫]有前驅(qū)的節(jié)點(入度為0)暫存到棧中,輸出時出棧即表示刪除。進行邊的刪除時將其鄰接點的入度減1即可。例如下圖中刪除 C0 的所有發(fā)出邊,相對于 C3、C2、C1 節(jié)點入度減1。

3.算法步驟

1 求各節(jié)點的入度,將其存入數(shù)組 indegree[] 中,并將入度為 0 的節(jié)點入棧 S。

2 如果棧不空,則重復執(zhí)行以下操作:將棧頂元素 i 出棧并保存到拓撲序列數(shù)組 topo[] 中;將節(jié)點 i 的所有鄰節(jié)點入度都減 1,如果減 1 后入度為 0,則立即入棧 S。

3 如果輸出的節(jié)點數(shù)少于 AOV 網(wǎng)中的節(jié)點數(shù),則說明網(wǎng)中有環(huán),否則輸出拓撲序列。

4.圖解

AOV 網(wǎng)如下圖所示。

1 輸入邊時,累加節(jié)點入度并保存到數(shù)組 indegree[] 中,將入度為0 的節(jié)點入棧 S。

2 將棧頂元素 5 出棧并保存到拓撲序列數(shù)組 topo[] 中。將節(jié)點 5 的所有鄰接點(C3、C4)入度都減1,如果減1后,入度為0,則立即入棧 S。

3  將棧頂元素 0 出棧并保存到拓撲序列數(shù)組 topo[] 中。將節(jié)點 0 的所有鄰接點(C1、C2、C4)入度都減1,如果減1后,入度為0,則立即入棧 S。

4 將棧頂元素 3 出棧并保存到拓撲序列數(shù)組 topo[] 中。將節(jié)點 3 的所有鄰接點(C4)入度都減1,如果減1后,入度為0,則立即入棧 S。

5 將棧頂元素 2 出棧并保存到拓撲序列數(shù)組 topo[] 中。將節(jié)點 2 的所有鄰接點(C1、C4)入度都減1,如果減1后,入度為0,則立即入棧 S。

6 將棧頂元素 4 出棧并保存到拓撲序列數(shù)組 topo[] 中。節(jié)點 4 沒有鄰接點。

7 將棧頂元素 1 出棧并保存到拓撲序列數(shù)組 topo[] 中。節(jié)點 1 沒有鄰接點。

8 ??眨惴ㄍV?。輸出拓撲排序序列。

拓撲排序算法實現(xiàn)

1.拓撲圖

2.實現(xiàn)代碼

package graph.topoSort;
 
import java.util.Scanner;
import java.util.Stack;
 
public class TopoSort {
    static final int maxn = 105;
    static int map[][] = new int[maxn][maxn];
    static int indegree[] = new int[maxn];
    static int topo[] = new int[maxn];
    static int n, m;
    static Stack<Integer> s = new Stack<>();
 
    static boolean TopoSort() { // 拓撲排序
        int cnt = 0;
        for (int i = 0; i < n; i++)
            if (indegree[i] == 0)
                s.push(i);
        while (!s.empty()) {
            int u = s.peek();
            s.pop();
            topo[cnt++] = u;
            for (int j = 0; j < n; j++)
                if (map[u][j] == 1)
                    if (--indegree[j] == 0)
                        s.push(j);
        }
        if (cnt < n) {
            return false;
        }
        return true;
    }
 
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        n = scanner.nextInt();
        m = scanner.nextInt();
 
        for (int i = 0; i < m; i++) {
            int u, v;
            u = scanner.nextInt();
            v = scanner.nextInt();
            map[u][v] = 1;
            indegree[v]++;
        }
        TopoSort();
        for (int i = 0; i < n - 1; i++)
            System.out.print(topo[i] + " ");
        System.out.println(topo[n - 1]);
    }
}

3.測試

以上就是Java實現(xiàn)拓撲排序算法的示例代碼的詳細內(nèi)容,更多關(guān)于Java拓撲排序算法的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 詳解Spring Data JPA中Repository的接口查詢方法

    詳解Spring Data JPA中Repository的接口查詢方法

    repository代理有兩種方式從方法名中派生出特定存儲查詢:通過直接從方法名派生查詢和通過使用一個手動定義的查詢。本文將通過示例詳細講解Spring Data JPA中Repository的接口查詢方法,需要的可以參考一下
    2022-04-04
  • Java多線程下的其他組件之CyclicBarrier、Callable、Future和FutureTask詳解

    Java多線程下的其他組件之CyclicBarrier、Callable、Future和FutureTask詳解

    這篇文章主要介紹了Java多線程下的其他組件之CyclicBarrier、Callable、Future和FutureTask詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-07-07
  • Spring?Boot?集成JWT實現(xiàn)前后端認證的示例代碼

    Spring?Boot?集成JWT實現(xiàn)前后端認證的示例代碼

    小程序、H5應用的快速發(fā)展,使得前后端分離已經(jīng)成為了趨勢,本文主要介紹了Spring?Boot?集成JWT實現(xiàn)前后端認證,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-04-04
  • Java反射學習 getClass()函數(shù)應用

    Java反射學習 getClass()函數(shù)應用

    所謂反射,可以理解為在運行時期獲取對象類型信息的操作,本文將詳細介紹,需要的朋友可以參考下
    2012-12-12
  • JavaWeb入門教程之分頁查詢功能的簡單實現(xiàn)

    JavaWeb入門教程之分頁查詢功能的簡單實現(xiàn)

    這篇文章主要介紹了JavaWeb入門教程之分頁查詢功能的簡單實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-11-11
  • Mybatis之#{}與${}的區(qū)別使用詳解

    Mybatis之#{}與${}的區(qū)別使用詳解

    這篇文章主要介紹了Mybatis之#{}與${}的區(qū)別詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-06-06
  • 淺談java String.split丟失結(jié)尾空字符串的問題

    淺談java String.split丟失結(jié)尾空字符串的問題

    下面小編就為大家?guī)硪黄獪\談java String.split丟失結(jié)尾空字符串的問題。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-02-02
  • java實現(xiàn)2048小游戲(含注釋)

    java實現(xiàn)2048小游戲(含注釋)

    這篇文章主要為大家介紹了java實現(xiàn)2048小游戲,含詳細注釋,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-04-04
  • Java樹形結(jié)構(gòu)數(shù)據(jù)生成導出excel文件方法記錄

    Java樹形結(jié)構(gòu)數(shù)據(jù)生成導出excel文件方法記錄

    最近好像得罪了poi,遇到的都是導出word、Excel、pdf的問題,下面這篇文章主要給大家介紹了關(guān)于Java樹形結(jié)構(gòu)數(shù)據(jù)生成導出excel文件的相關(guān)資料,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考下
    2021-10-10
  • Springboot配置管理Externalized?Configuration深入探究

    Springboot配置管理Externalized?Configuration深入探究

    這篇文章主要介紹了Springboot配置管Externalized?Configuration深入探究,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2024-01-01

最新評論