TA的每日心情 | 开心 2021-3-12 23:18 |
---|
签到天数: 2 天 [LV.1]初来乍到
|
对一个有向无环图(Directed Acyclic Graph简称DAG)G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若<u,v> ∈E(G),则u在线性序列中出现在v之前。
通常,这样的线性序列称为满足拓扑次序(TopoiSicai Order)的序列,简称拓扑序列。
注意:
①若将图中顶点按拓扑次序排成一行,则图中所有的有向边均是从左指向右的。
②若图中存在有向环,则不可能使顶点满足拓扑次序。
③一个DAG的拓扑序列通常表示某种方案切实可行。
【例】一本书的作者将书本中的各章节学习作为顶点,各章节的先学后修关系作为边,构成一个有向图。按有向图的拓扑次序安排章节,才能保证读者在学习某章节时,其预备知识已在前面的章节里介绍过。
④一个DAG可能有多个拓扑序列。
【例】对图G9进行拓扑排序,至少可得到如下的两个(实际远不止两个)拓扑序列:C0,C1,C2,C4,C3,C5,C7,C8,C6和C0,C6,C7,C1,C4,C2,C3,C8,C5。
⑤当有向图中存在有向环时,拓扑序列不存在
无后继的顶点优先拓扑排序方法
1、思想方法
该方法的每一步均是输出当前无后继(即出度为0)的顶点。对于一个DAG,按此方法输出的序列是逆拓扑次序。因此设置一个栈(或向量)T来保存输出的顶点序列,即可得到拓扑序列。若T是栈,则每当输出顶点时,只需做人栈操作,排序完成时将栈中顶点依次出栈即可得拓扑序列。若T是向量,则将输出的顶点从T[n-1]开始依次从后往前存放,即可保证T中存储的顶点是拓扑序列。
2、抽象算法描述
算法的抽象描述为:
NonSuccFirstTopSort(G){//优先输出无后继的顶点
while(G中有出度为0的顶点)do {
从G中选一出度为0的顶点v且输出v;
从G中删去v及v的所有人边
}
if(输出的顶点数目<|V(G)|)
Error("G中存在有向环,排序失败!");
}
代码:- //有向无环图的拓扑排序:
- //第一步:在图中找到一个没有后继的顶点;
- //第二步:从图中删除这个顶点,在列表的前面插入顶点的标记
- //第三步:重复第一和第二步,直到所有顶点都从图中删除。这时列表显示的顶点顺序就是拓扑排序的结果。
- class Vertex {
- public char label;
- public Vertex(char lab)
- { label = lab; }
- }
- class Graph{
- private final int MAX_VERTS = 20;
- private Vertex vertexList[]; //顶点列表
- private int adjMat[][]; //邻接矩阵
- private int nVerts; // 当前的顶点数
- private char sortedArray[];// 已经排序的顶点
- Graph() {
- vertexList = new Vertex[MAX_VERTS];
-
- adjMat = new int[MAX_VERTS][MAX_VERTS];
- nVerts = 0;
- for(int j=0; j< MAX_VERTS; j++)
- for(int k=0; k< MAX_VERTS; k++)
- adjMat[j][k] = 0;
- sortedArray = new char[MAX_VERTS];
- }
- public void addVertex(char lab)//在图中增加一个顶点
- {
- vertexList[nVerts++] = new Vertex(lab);
- }
- public void addEdge(int start, int end)//在图中增加一条边
- {
- adjMat[start][end] = 1;
- }
- public void displayVertex(int v)
- {
- System.out.print(vertexList[v].label);
- }
- public void topo(){
- int orig_nVerts = nVerts;
- while(nVerts > 0){
-
- int currentVertex = noSuccessors();//找一个没有后继的顶点(出度为0)
-
- if(currentVertex == -1){ // 没有找到,一定是一个环
- System.out.println("ERROR: Graph has cycles");
- return;
- }
- // 找到了,插入
- sortedArray[nVerts-1] = vertexList[currentVertex].label;
- deleteVertex(currentVertex); // 删除顶点
- }
- // 显示拓扑排序的结果
- System.out.print("Topologically sorted order: ");
- for(int j=0; j< orig_nVerts; j++)
- System.out.print( sortedArray[j] );
- System.out.println("");
- }
- public int noSuccessors(){ // 从邻接矩阵中找一个没有后继的顶点(出度为0的)
- boolean isEdge;
- for(int row=0; row< nVerts; row++){
- isEdge = false;
- for(int col=0; col< nVerts; col++){
- if( adjMat[row][col] > 0 ){
- isEdge = true;
- break;
- }
- }
- if( !isEdge )
- return row;
- }
- return -1;
- }
- //删除一个顶点。顶点从vertexList[]数组删除,后面的顶点向前移动填补空位,同样的,顶点所在的行列
- //从邻接矩阵中删除,下面的行的右面的列移动来填补空位。
- public void deleteVertex(int delVert){
- if(delVert != nVerts-1) {// 如果不是最后一个顶点
- for(int j=delVert; j< nVerts-1; j++)
- vertexList[j] = vertexList[j+1];
- // 在邻接矩阵中删除一行
- for(int row=delVert; row< nVerts-1; row++)
- moveRowUp(row, nVerts);
- // 在邻接矩阵中删除一列
- for(int col=delVert; col< nVerts-1; col++)
- moveColLeft(col, nVerts-1);
- }
- nVerts--;
- }
- private void moveRowUp(int row, int length){
- for(int col=0; col< length; col++)
- adjMat[row][col] = adjMat[row+1][col];
- }
- private void moveColLeft(int col, int length){
- for(int row=0; row< length; row++)
- adjMat[row][col] = adjMat[row][col+1];
- }
- }
- public class TopoApp {
- public static void main(String[] args){
- Graph theGraph = new Graph();
- theGraph.addVertex("0");
- theGraph.addVertex("1");
- theGraph.addVertex("2");
- theGraph.addVertex("3");
- theGraph.addVertex("4");
- theGraph.addVertex("5");
- theGraph.addVertex("6");
- theGraph.addVertex("7");
- theGraph.addVertex("8");
- theGraph.addEdge(0, 6);
- theGraph.addEdge(0, 2);
- theGraph.addEdge(6, 7);
- theGraph.addEdge(7, 8);
- theGraph.addEdge(2, 3);
- theGraph.addEdge(1, 2);
- theGraph.addEdge(1, 4);
- theGraph.addEdge(4, 5);
- theGraph.addEdge(4, 3);
- theGraph.addEdge(3, 5);
- theGraph.addEdge(3, 8);
-
- theGraph.topo(); // do the sort
- }
- }
复制代码 运行结果:
C: est>java TopoApp
Topologically sorted order: 067142385
源码下载:http://file.javaxxz.com/2014/12/7/000708140.zip |
|