首頁 Java java教程 有向圖之任務調度拓樸圖介紹

有向圖之任務調度拓樸圖介紹

Jun 25, 2017 am 10:59 AM
任務 調度

1.有向圖的資料型別

#使用Bag表示有向圖,其中邊v->w表示為頂點v所對應的鄰接鍊錶包含一個w頂點,與無向圖不同的是,這裡每條邊只會出現一次.有向圖的資料結構型別如下:

public class Digraph {private final int V;private int E;private Bag<Integer>[] adj;public Digraph(int V) {this.V=V;this.E=0;
        adj=(Bag<Integer>[])new Bag[V];for(int v=0;v<V;v++) {
            adj[v]=new Bag<Integer>();
        }
    }public int V() {return V;
    }public int E() {return E;
    }//添加一条边v->w,由于是有向图只要添加一条边就可以了public void addEdge(int v,int w) {
        adj[v].add(w);
        E++;
    }public Iterable<Integer> adj(int v) {return adj[v];
    }//返回当前图的一个反向的图public Digraph reverse() {
        Digraph R=new Digraph(V);for(int v=0;v<V;v++) {for(int w:adj(v)) {
                R.addEdge(w, v);
            }
        }return R;
    }
}
登入後複製

 

2.有向圖中的可達性

無向圖的連結性相似,同利用深度優先搜尋可以解決有向圖中

單點可達性問題:即:給定一幅有向圖和一個起點s,回答是否存在一條從s到達給定頂點v的有向路徑的問題.

多點可達性問題:給定一幅有向圖和頂點的集合,回答是否存在一條從集合中的任意頂點到達給定頂點v的有向路徑?

public class DirectedDFS {private boolean[] marked;//从G中找出所有s可达的点public DirectedDFS(Digraph G,int s) {
        marked=new boolean[G.V()];
        dfs(G,s);
    }//G中找出一系列点可达的点public DirectedDFS(Digraph G,Iterable<Integer> sources) {
        marked=new boolean[G.V()];for(int s:sources) {if(!marked[s]) dfs(G,s);
        }
    }//深度优先搜素判断.private void dfs(Digraph G, int v) { 
        marked[v]=true;for(int w:G.adj(v)) {if(!marked[w]) dfs(G,w);
        }
    }//v是可达的吗public boolean marked(int v) {return marked[v];
    }
}
登入後複製

多點可達性問題的一個重要時機應用是在典型的記憶體管理系統中,包括許多java的實作。在一個有向圖中,一個頂點表示一個對象,一邊則表示一個物件對另一個物件的參考。

這個模型很好表現了運行中的java程式的記憶體使用狀況。在程式執行的任何時候都有某些物件是可以被直接存取的,而不能透過這些物件存取到的所有物件都應該被回收以便

釋放記憶體。它會週期性的運行一個類似DirectedDFS的有向圖可達性演算法來標記所有可以被存取的物件。

 

3.有向圖的尋路

和無向圖類似,有向圖中常見的問題:

單點有向路徑。給定一幅有向圖和一個起點,回答「從s到給定目的頂點v是否存在一條有向路徑?如果有,找出這條路徑」

單點最短有向路徑。 給定一幅有向圖和一個起點,回答「從s到給定目的頂點v是否存在一條有向路徑,如果有,找出其中最短的那條(所含邊數最少)」

 

4.調度問題—拓樸排序

4.1尋找有向環

如果一個有優先限制的問題中存在有向環,那麼這個問題肯定是無解的。所以需要進行有向環的檢測。

下面的程式碼可以用來偵測給定的有向圖中是否含有有向環,如果有,則按照路徑的方向返回環上的所有頂點.

在執行dfs的時候,查找的是從起點到v的有向路徑,onStack數組標記了遞歸調用的棧上的所有頂點,同時也加入了edgeTo數組,在找到有向環的時候返回環中的所有頂點.

##
/**
 * 有向图G是否含有有向环
 * 获取有向环中的所有顶点
 * @author Administrator
 * */public class DirectedCycle {private boolean[] marked;    private int[] edgeTo;private Stack<Integer> cycle;    //有向环中的所有顶点private boolean[] onStack;        //递归调用的栈上的所有顶点public DirectedCycle(Digraph G) {
        edgeTo=new int[G.V()];
        onStack=new boolean[G.V()];
        marked=new boolean[G.V()];for(int v=0;v<G.V();v++) {if(!marked[v]) dfs(G,v);
        }
    }/**
 * 该算法的关键步骤在于onStack数组的运用.
 * onStack数组标记的是当前遍历的点.如果对于一个点指向的所有点中的某个点
 * onstack[v]=true.代表该点正在被遍历也就是说
 * 该点存在一条路径,指向这个点.而这个点现在又可以指向该点,
 * 即存在环的结构~
 * @param G
 * @param v */ private void dfs(Digraph G, int v) {
        onStack[v]=true;
        marked[v]=true;for(int w:G.adj(v)) {if(this.hasCycle()) return;else if(!marked[w]) {
                edgeTo[w]=v;
                dfs(G,w);
            }else if(onStack[w]) {
                cycle=new Stack<Integer>();for(int x=v;x!=w;x=edgeTo[x])
                    cycle.push(x);
                cycle.push(w);
                cycle.push(v);
            }
        }//dfs方法结束,对于该点的递归调用结束.该点指向的所有点已经遍历完毕onStack[v]=false;
    }private boolean hasCycle() {return cycle!=null;
    }public Iterable<Integer> cycle() {return cycle;
    }
}
登入後複製
 

4.2 拓撲排序

拓補排序:給定一幅有向圖,將所有的頂點排序,使得所有的有向邊均從排在前面的元素指向排在後面的元素.如果存在有向環的話,那麼拓補排序無法完成.############  要實現有向圖的拓補排序,利用標準深度優先搜尋順序即可完成任務.這裡頂點會有三種排列順序: ############  1.前序:在遞歸呼叫前將頂點加入佇列############  2.後序:在遞歸呼叫之後將頂點加入佇列############  3.逆後序:在遞歸呼叫之後將頂點壓入堆疊.############  具體的操作見下面的程式碼:## #######
//有向图中基于深度优先搜索的拓补排序public class DepthFirstOrder {private boolean[] marked;private Queue<Integer> pre;        //所有顶点的前序排列private Queue<Integer> post;    //所有顶点的后序排列private Stack<Integer> reversePost;//所有顶点的逆后序排列public DepthFirstOrder(Digraph G) {
        pre=new Queue<>();
        post=new Queue<>();
        reversePost=new Stack<>();
        marked=new boolean[G.V()];        for(int v=0;v<G.V();v++) {if(!marked[v]) dfs(G,v);
        }
    }private void dfs(Digraph G, int v) {        pre.enqueue(v);marked[v]=true;for(int w:G.adj(v)) {if(!marked[w]) {
                dfs(G,w);
            }
        }        post.enqueue(v);    reversePost.push(v);}public Iterable<Integer> pre() {return pre;
    }public Iterable<Integer> post() {return post;
    }public Iterable<Integer> reversePost() {return reversePost;
    }
}
登入後複製
###

遍历的顺序取决于这个数据结构的性质以及是在递归调用之前还是之后进行保存。

前序:在递归调用之前将顶点加入队列。

后序:在递归调用之后将顶点加入队列。

逆后序:在递归调用之后将顶点压入栈。

 

前序就时dfs()的调用顺序;后序就是顶点遍历完成的顺序;逆后序就是顶点遍历完成顺序的逆。

拓补排序的实现依赖于上面的API,实际上拓补排序即为所有顶点的逆后序排列

拓补排序的代码如下:

public class Topological {private Iterable<Integer> order;    //顶点的拓补排序public Topological(Digraph G) {
        DirectedCycle cyclefinder=new DirectedCycle(G);if(!cyclefinder.hasCycle()) {//只有无环才能进行拓补排序DepthFirstOrder dfs=new DepthFirstOrder(G);
            order=dfs.reversePost();
        }
    }public Iterable<Integer> order() {return order;
    }public boolean isDAG() {return order!=null;
    }
}
登入後複製

 

5.有向图的强连通性

定义:如果两个顶点v和w是互相可达的,则称它们为强连通的.也就是说既存在一条从v到w的有向路径也存在一条从w到v的有向路径.

如果一幅有向图中的任意两个顶点都是强连通的,则称这副有向图也是强连通的.任意顶点和自己都是强连通的.

下面的代码采用如下步骤来计算强连通分量以及两个点是否是强连通的:

  1.在给定的有向图中,使用DepthFirsetOrder来计算它的反向图GR的逆后序排列

  2.按照第一步计算得到的顺序采用深度优先搜索来访问所有未被标记的点

  3.在构造函数中,所有在同一个递归dfs()调用中被访问到的顶点都是在同一个强连通分量中.

  下面的代码实现遵循了上面的思路:

/**
 * 该算法实现的关键:
 * 使用深度优先搜索查找给定有向图的反向图GR.根据由此得到的所有顶点的逆后序
 * 再次用深度优先搜索处理有向图G.其构造函数的每一次递归调用所标记的顶点都在
 * 同一个强连通分量中.
 * 解决问题:
 * 判断两个点是否是强连通的
 * 判断总共有多少个连通分量
 * @author Administrator
 * */public class KosarajuSCC {private boolean[] marked;//已经访问过的顶点private int[] id;        //强连通分量的标识符private int count;        //强联通分量的数量public KosarajuSCC(Digraph G) {
        marked=new boolean[G.V()];
        id=new int[G.V()];
        DepthFirstOrder order=new DepthFirstOrder(G.reverse());for(int s:order.reversePost()) {if(!marked[s]) {
                dfs(G,s);
                count++;
            }
        }
    }private void dfs(Digraph G, int v) {
        marked[v]=true;
        id[v]=count;for(int w:G.adj(v)) {if(!marked[w]) {
                dfs(G,w);
            }
        }
    }public boolean stronglyConnected(int v,int w) {return id[v]==id[w];
    }public int id(int v) {return id[v];
    }public int count() {return count;
    }
}
登入後複製

 

以上是有向圖之任務調度拓樸圖介紹的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

<🎜>:泡泡膠模擬器無窮大 - 如何獲取和使用皇家鑰匙
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
北端:融合系統,解釋
3 週前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

Java教學
1664
14
CakePHP 教程
1423
52
Laravel 教程
1319
25
PHP教程
1269
29
C# 教程
1248
24
模擬山羊3恐怖走廊任務怎麼做 模擬山羊3恐怖走廊任務怎麼做 Feb 25, 2024 pm 03:40 PM

恐怖走廊是模擬山羊3之中的一個任務,這個任務要怎麼樣才能夠去完成呢,掌握到詳細的過關方式和對應的流程,能夠完成這個任務的相應挑戰,下面就為大家帶來模擬山羊3恐怖走廊攻略,了解相關的資訊。模擬山羊3恐怖走廊攻略1、首先需要玩家前往地圖左上角的寂靜嶺處。 2.在這裡可以看到一個屋頂上寫著RESTSTOP的房子,玩家需要操作山羊進入這棟房子。 3.進入房間​​之後,我們先向前直走,然後向右轉,在這裡盡頭有一扇門,我們直接從這裡進去。 4.進入之後同樣是先向前走隨後右轉,在這裡走到門前門會關上,我們需要回頭找到

修正: 操作員拒絕 Windows 工作排程程式中的要求錯誤 修正: 操作員拒絕 Windows 工作排程程式中的要求錯誤 Aug 01, 2023 pm 08:43 PM

要自動化任務和管理多個系統,任務規劃軟體是您武器庫中的寶貴工具,尤其是對於系統管理員而言。 Windows任務規劃程式完美地完成了這項工作,但最近許多人報告說操作員拒絕了請求錯誤。這個問題存在於作業系統的所有迭代中,即使已經廣泛報告和涵蓋,也沒有有效的解決方案。繼續閱讀以找到真正對其他人有用的內容!操作員或管理員拒絕了任務計畫程式0x800710e0中的請求是什麼?任務計劃程式允許在沒有使用者輸入的情況下自動執行各種任務和應用程式。您可以使用它來安排和組織特定應用程式、配置自動通知、幫助傳遞訊息等。它

模擬山羊3帝陵任務怎麼過 模擬山羊3帝陵任務怎麼過 Mar 11, 2024 pm 01:10 PM

模擬山羊3是有著經典模擬玩法的遊戲,可讓玩家充分體驗到休閒動作類操作模擬的樂趣,遊戲中還擁有很多特色任務的精彩,其中模擬山羊3帝陵任務是需要玩家找尋到鐘塔上的三個鐘並操作的,有些玩家還不清楚要怎麼弄,下面帶來模擬山羊3帝陵任務攻略流程分享!模擬山羊3帝陵任務攻略流程按照順序敲擊鐘即可。詳細步驟拓展1、首先玩家需要打開地圖到霧丘公墓。 2.然後上到鐘樓上,裡面會有三個鐘。 3.接著按照從大到小的順序,依照222312312熟悉怒敲擊。 4、完成敲擊後即可完成任務,並打開大門以獲得光劍。

模擬山羊3營救史蒂夫任務怎麼做 模擬山羊3營救史蒂夫任務怎麼做 Feb 25, 2024 pm 03:34 PM

營救史蒂夫是模擬山羊3中的一個獨特任務,具體需要怎麼做才能夠完成呢,這個任務比較簡單,但是我們需要注意不要理解錯意思,下面就為大家帶來模擬山羊3營救史蒂夫任務攻略,能夠更好的完成相關的任務。模擬山羊3營救史蒂夫任務攻略1、先來到地圖中右下角的溫泉。 2.在來到溫泉邊之後就可以觸發營救史蒂夫的這個任務。 3.注意在溫泉裡有個男人,雖然他也叫史蒂夫,但是並不是這次任務的目標。 4.在這個溫泉裡找到一條叫史蒂夫的魚,並且將其帶上岸,即可完成這個任務。

抖音粉絲團任務在哪裡看?抖音粉絲團會掉等級嗎? 抖音粉絲團任務在哪裡看?抖音粉絲團會掉等級嗎? Mar 07, 2024 pm 05:25 PM

抖音作為當下最受歡迎的社群媒體平台之一,吸引了大量用戶參與其中。在抖音上,有許多粉絲團任務可供用戶完成,以獲得一定的獎勵和福利。那麼,抖音粉絲團任務在哪裡可以找到呢?一、抖音粉絲團任務在哪裡看?為了找到抖音粉絲團任務,你需要造訪抖音的個人首頁。在主頁上,你會看到一個名為「粉絲團」的選項。點擊這個選項,你就可以瀏覽你所加入的粉絲團和相關任務。在粉絲團任務欄位中,你會看到各種不同類型的任務,例如按讚、留言、分享、轉發等。每個任務都有對應的獎勵和要求,一般來說,完成任務後會獲得一定數量的金幣或經驗值

時序分析五邊形戰士!清華提出TimesNet:預測、填補、分類、偵測全面領先 時序分析五邊形戰士!清華提出TimesNet:預測、填補、分類、偵測全面領先 Apr 11, 2023 pm 07:34 PM

實現任務通用是深度學習基礎模型研究的核心問題,也是近期大模型方向的主要關注點之一。然而,在時間序列領域,各類分析任務的差異較大,既有需要細粒度建模的預測任務,也有需要擷取高層語意資訊的分類任務。如何建構統一的深度基礎模型有效率地完成各類時序分析任務,此前尚未有成型方案。為此,來自清華大學軟體學院的團隊圍繞時序變化建模這一基本問題展開研究,提出了任務通用的時序基礎模型TimesNet,論文被ICLR 2023接收。作者列表:吳海旭*,胡騰戈*,劉雍*,週航,王建民,龍明盛連結:https://ope

如何在 Windows 11 中停止工作管理員進程更新並更方便地終止任務 如何在 Windows 11 中停止工作管理員進程更新並更方便地終止任務 Aug 20, 2023 am 11:05 AM

如何在Windows11和Windows10中暫停工作管理員進程更新按CTRL+視窗鍵+刪除開啟工作管理員。預設情況下,任務管理器將開啟「進程」視窗。正如您在此處看到的,所有應用程式都在無休止地移動,當您想要選擇它們時,可能很難將它們指向下方。因此,按CTRL並按住它,這將暫停任務管理器。您仍然可以選擇應用程序,甚至可以向下捲動,但您必須始終按住CTRL按鈕。

如何在 macOS 中停用「按一下桌面顯示」功能 如何在 macOS 中停用「按一下桌面顯示」功能 Nov 23, 2023 pm 02:31 PM

預設情況下,macOSSonoma會在您按一下桌面桌布時隱藏所有活動視窗。如果您傾向於在桌面上有一堆需要存取的文件,這將很方便。但是,如果您發現這種行為令人抓狂,則有一種方法可以將其關閉。 Apple最新的macOSSonomaMac作業系統有一個新選項,稱為「點擊壁紙以顯示桌面」。預設情況下啟用,如果您傾向於打開多個窗口,並且想要訪問桌面上的文件或資料夾,而不必最小化或移動窗口,則該選項可能特別有用。啟用該功能並點擊桌面牆紙後,所有開啟的視窗都會暫時被掃到一邊,從而直接存取桌面。完成後,您可以再次

See all articles