深度优先 有向java,深度优先搜索与有向无环图的拓扑排序(java兑现)

深度优先搜索与有向无环图的拓扑排序(java实现)

当每个任务有前后置关系时,需要找到一种满足前后置关系的路线,将任务完成。

如果将每个任务看成一个节点,任务之间的前后置关系表示为有向图时,这种路线顺序叫做为图进行拓扑排序。也叫关键路径分析。

比如有很多任务T1,T2,....

这些任务又是相互关联的,比如Tj完成前必须要求Ti已完成,这样T1,T2....序列关于这样的先决条件构成一个图,其中如果Ti必须要先于Tj完成,那么就是该图中的一条路径,路径长度为1的就是一条边。拓扑排序就是把这些任务按照完成的先后顺序排列出来。显然,这样的顺序可能不是唯一的,比如Tk,Tl如果没有在一条路径上,那么他们之间的顺序是任意的。

当从某顶点v出发的DFS搜索完成时,v的所有后继必定均已被访问过(想像它们均已被删除),此时的v相当于是无后继的顶点,因此在DFS算法返回之前输出顶点v即可得到 DAG的逆拓扑序列。

其中第一个输出的顶点必是无后继(出度为0)的顶点,它应是拓扑序列的最后一个顶点。若希望得到的不是逆拓扑序列,同样可增加T来保存输出的顶点。假设T是栈。

利用DFS求拓扑序列的抽象算法可描述为:

void DFSTopSort(G,i,T){//i是搜索的出发点,T是栈

int j;

visited[i]=TRUE; //访问i

for(所有i的邻接点j)//即∈E(G)

if(!visited[j])

DFSTopSort(G,j,T);

Push(&T,i); //从i出发的搜索已完成,输出i

}

看看下图的一个拓扑序列:

[c1, c4, c0, c2, c3, c5, c6, c7, c8]

1335421576.png

public enum VertexState {

UNVISITED,VISITED,PASSED;//未访问,已访问,已经过

}

import java.util.Set;

import java.util.List;

import java.util.HashSet;

import java.util.ArrayList;

import java.util.Collections;

//顶点类

class Vertex

{

private String label;

private VertexState state;//顶点状态

public Vertex(String lab)

{

label = lab;

state = VertexState.UNVISITED;

}

public VertexState getState(){

return state;

}

public void setState(VertexState state){

this.state=state;

}

public String toString(){

return label;

}

}

//有向图的邻接矩阵实现

class Graph

{

private final int MAX_VERTS = 30;

private Vertex vertexList[]; // 存放顶点的数组

private int adjMat[][]; // 邻接矩阵

private int nVerts; // 当前的顶点数

public Graph()

{

vertexList = new Vertex[MAX_VERTS];

adjMat = new int[MAX_VERTS][MAX_VERTS];

nVerts = 0;

for(int y=0; y

for(int x=0; x

adjMat[x][y] = 0;

}

public void addVertex(Vertex v)//在图中添加一个顶点

{

vertexList[nVerts++] = v;

}

//在图中增加一条边,从start到end

public void addEdge(int start, int end)

{

adjMat[start][end] = 1;

}

/**

* 返回v顶点所关联的邻结点

* @param v

* @return

*/

private Set getNeighbors(Vertex v){

Set vSet = new HashSet();

int index=getIndex(v);

if(index==-1) return null;

for(int i=0;i

if(adjMat[index][i]==1)

vSet.add(vertexList[i]);

return vSet;

}

//返回顶点在vertexList数组中的索引

private int getIndex(Vertex v){

for(int i=0;i

if(vertexList[i]==v)

return i;

return -1;

}

/**

* 全部节点设为未访问

*/

private void allUnVisted(){

Vertex v=null;

int len = nVerts;

for(int i = 0; i < len ; i++){

v = vertexList[i];

if(v.getState() != VertexState.UNVISITED){

v.setState(VertexState.UNVISITED);

}

}

}

private boolean containsVertex(Vertex v){

int index=getIndex(v);

if(index!=-1) return true;

else return false;

}

private VertexState getState(Vertex v){

return v.getState();

}

private VertexState setState(Vertex v, VertexState state) {

VertexState preState = v.getState();

v.setState(state);

return preState;

}

/**

* 深度优先遍历一个顶点

* @param

* @param graph

* @param v

* @param checkCycle

* @return

*/

public List dfs(Vertex v,boolean checkCycle){

allUnVisted();

List vList = new ArrayList();

dfsHandler(v,checkCycle,vList);

return vList;

}

private void dfsHandler(Vertex v,boolean checkCycle,List vList){

Set neighbors = null;

if(!containsVertex(v)){

throw new IllegalStateException("不存在该顶点");

}

setState(v, VertexState.PASSED);

neighbors = getNeighbors(v);

VertexState state = null;

for(Vertex neighbor : neighbors){

state = getState(neighbor);

if(state == VertexState.UNVISITED){//未遍历,

// System.out.println(neighbor+",");

dfsHandler(neighbor, checkCycle, vList);

}else if(state == VertexState.PASSED && checkCycle){//

throw new IllegalStateException("存在一个环");

}

}

setState(v, VertexState.VISITED);//访问结束设为已访问

vList.add(v);

// System.out.println("++"+v);

}

/**

* 图的拓扑排序

*/

public List topo(){

List vList = new ArrayList();

allUnVisted();

for(int i=0;i

if(getState(vertexList[i]) == VertexState.UNVISITED){

try{

dfsHandler(vertexList[i], true, vList);

}catch (IllegalStateException e) {

throw new IllegalStateException("图有一个环");

}

}

}

Collections.reverse(vList);

return vList;

}

}

public class DFSApp

{

public static void main(String[] args)

{

Graph theGraph = new Graph();

Vertex v1=new Vertex("c0");

Vertex v2=new Vertex("c1");

Vertex v3=new Vertex("c2");

Vertex v4=new Vertex("c3");

Vertex v5=new Vertex("c4");

Vertex v6=new Vertex("c5");

Vertex v7=new Vertex("c6");

Vertex v8=new Vertex("c7");

Vertex v9=new Vertex("c8");

theGraph.addVertex(v1); // 0

theGraph.addVertex(v2); // 1

theGraph.addVertex(v3); // 2

theGraph.addVertex(v4); // 3

theGraph.addVertex(v5); // 4

theGraph.addVertex(v6); // 5

theGraph.addVertex(v7); // 6

theGraph.addVertex(v8); // 7

theGraph.addVertex(v9); // 8

theGraph.addEdge(0, 6); // c0->c6

theGraph.addEdge(0, 2); // c0->c2

theGraph.addEdge(3, 5); // c3->c5

theGraph.addEdge(3, 8); // c3->c8

theGraph.addEdge(1, 2); // c1->c2

theGraph.addEdge(1, 4); // c1->c4

theGraph.addEdge(2, 3); // c2->c3

theGraph.addEdge(6, 7); // c6->c7

theGraph.addEdge(7, 8); // c7->c8

theGraph.addEdge(4, 3); // c4->c3

theGraph.addEdge(4, 5); // c4->c5

//theGraph.addEdge(3, 1); // c3->c1

System.out.print("Visits: ");

List vl=theGraph.topo();

// List vl=theGraph.dfs(v1,false);

System.out.println(vl);

}

}

下载源文件:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值