您的位置:首页 > 编程语言 > Java开发

拓扑排序(TopologicalSort) Java实现

2017-03-01 16:03 489 查看
在一个表示工程的有向图中,用顶点表示活动,用弧表示活动之间的优先关系,这样的有向图为顶点表示活动的网,我们称之为AOV网(Active On Vertex Network)
AOV网不能存在回路
拓扑排序含义
设G=(V,E)是一个具有n个顶点的有向图,V中的顶点序列V1,V2,....,Vn满足若从顶点Vi到Vj有一条路径,则在顶点序列中顶点Vi必在顶点Vj之前。则我们称这样的顶点序列为一个拓扑排序。
所谓拓扑排序,其实就是对一个有向图构造拓扑序列的过程
拓扑排序算法(TopologicalSort)
对AOV网进行拓扑排序的方法和步骤如下:
1.从AOV网中选择一个没有前驱的顶点(该顶点的入度为0)并且输出它;
2.从网中删去该顶点,并且删去从该顶点发出的全部有向边;
3.重复上述两步,直到剩余网中不再存在没有前驱的顶点为止。

代码示例图:





代码:
public class Topological {

/**
* 顶点数组
*/
private List<VertexNode> vexList;

/**
* 创建图(邻接表)
*/
public void createGraph(){
//v0
VertexNode v0 = new VertexNode(0, 0, null);

EdgeNode v0e0 = new EdgeNode(11, 0, null);
EdgeNode v0e1 = new EdgeNode(5, 0, null);
EdgeNode v0e2 = new EdgeNode(4, 0, null);

v0.setFirstEdge(v0e0);
v0e0.setNext(v0e1);
v0e1.setNext(v0e2);

//v1
VertexNode v1 = new VertexNode(0, 1, null);

EdgeNode v1e0 = new EdgeNode(8, 0, null);
EdgeNode v1e1 = new EdgeNode(4, 0, null);
EdgeNode v1e2 = new EdgeNode(2, 0, null);

v1.setFirstEdge(v1e0);
v1e0.setNext(v1e1);
v1e1.setNext(v1e2);

//v2
VertexNode v2 = new VertexNode(2, 2, null);

EdgeNode v2e0 = new EdgeNode(9, 0, null);
EdgeNode v2e1 = new EdgeNode(6, 0, null);
EdgeNode v2e2 = new EdgeNode(5, 0, null);

v2.setFirstEdge(v2e0);
v2e0.setNext(v2e1);
v2e1.setNext(v2e2);

//v3
VertexNode v3 = new VertexNode(0, 3, null);

EdgeNode v3e0 = new EdgeNode(13, 0, null);
EdgeNode v3e1 = new EdgeNode(2, 0, null);

v3.setFirstEdge(v3e0);
v3e0.setNext(v3e1);

//v4
VertexNode v4 = new VertexNode(2, 4, null);

EdgeNode v4e0 = new EdgeNode(7, 0, null);

v4.setFirstEdge(v4e0);

//v5
VertexNode v5 = new VertexNode(3, 5, null);

EdgeNode v5e0 = new EdgeNode(12, 0, null);
EdgeNode v5e1 = new EdgeNode(8, 0, null);

v5.setFirstEdge(v5e0);
v5e0.setNext(v5e1);

//v6
VertexNode v6 = new VertexNode(1, 6, null);

EdgeNode v6e0 = new EdgeNode(5, 0, null);

v6.setFirstEdge(v6e0);

//v7
VertexNode v7 = new VertexNode(2, 7, null);

//v8
VertexNode v8 = new VertexNode(2, 8, null);

EdgeNode v8e0 = new EdgeNode(7, 0, null);

v8.setFirstEdge(v8e0);

//v9 入度应为2,不是图片中的1(图片中已经改过来了)
VertexNode v9 = new VertexNode(2, 9, null);

EdgeNode v9e0 = new EdgeNode(11, 0, null);
EdgeNode v9e1 = new EdgeNode(10, 0, null);

v9.setFirstEdge(v9e0);
v9e0.setNext(v9e1);

//v10
VertexNode v10 = new VertexNode(1, 10, null);

EdgeNode v10e0 = new EdgeNode(13, 0, null);

v10.setFirstEdge(v10e0);

//v11
VertexNode v11 = new VertexNode(2, 11, null);

//v12
VertexNode v12 = new VertexNode(1, 12, null);

EdgeNode v12e0 = new EdgeNode(9, 0, null);

v12.setFirstEdge(v12e0);

//v13
VertexNode v13 = new VertexNode(2, 13, null);

vexList = new ArrayList<>();
vexList.add(v0);
vexList.add(v1);
vexList.add(v2);
vexList.add(v3);
vexList.add(v4);
vexList.add(v5);
vexList.add(v6);
vexList.add(v7);
vexList.add(v8);
vexList.add(v9);
vexList.add(v10);
vexList.add(v11);
vexList.add(v12);
vexList.add(v13);

}

public boolean topologicalSort() {
//统计输出顶点数
int count = 0;

//建栈存储入度为0的顶点
Stack<Integer> stack = new Stack<>();

//统计入度数(录入也可以,但是示例图的v9的度应为2,示例图中误写为1,导致查了半天bug,自动统计入度数看来也是有必要的)
for (int i = 0;i < vexList.size(); i++) {
vexList.get(i).setIn(0);
}
for (int i = 0;i < vexList.size(); i++) {

EdgeNode edge = vexList.get(i).getFirstEdge();
while (edge != null) {
VertexNode vex = vexList.get(edge.getAdjvex());
vex.setIn(vex.getIn() + 1);

edge = edge.getNext();
}
}

//将入度为0 的顶点入栈
for (int i = 0;i < vexList.size(); i++) {
if (vexList.get(i).getIn() == 0) {
stack.push(i);
}
}

while (!stack.isEmpty()) {
//栈顶 顶点出栈
int vexIndex = stack.pop();
System.out.print(vexIndex + " ");

count++;

//从顶点表结点中取出第一个边表结点
EdgeNode edge = vexList.get(vexIndex).getFirstEdge();

while (edge != null) {
int adjvex = edge.getAdjvex();

VertexNode vex = vexList.get(adjvex);

//将此 顶点的入度减一
vex.setIn(vex.getIn() - 1);
//此顶点的入度为零则入栈,以便于下次循环输出
if (vex.getIn() == 0) {
stack.push(adjvex);
}

edge = edge.getNext();

}
}

if (count != vexList.size())
return false;
else
return true;
}

public static void main(String[] args) {
Topological topological = new Topological();
topological.createGraph();
boolean success = topological.topologicalSort();

if (success) {
System.out.println("成功");
}else {
System.out.println("失败,有回路");
}
}

}

/**
* 边表结点
*
*/
class EdgeNode {
/**
* 邻接点域,存储该顶点对应的下标
*/
private int adjvex;

/**
* 用于存储权值,对于非网图可以不需要
*/
private int weight;

/**
* 链域,指向下一个邻接点
*/
private EdgeNode next;

public EdgeNode(int adjvex, int weight, EdgeNode next) {
super();
this.adjvex = adjvex;
this.weight = weight;
this.next = next;
}

public int getAdjvex() {
return adjvex;
}

public void setAdjvex(int adjvex) {
this.adjvex = adjvex;
}

public int getWeight() {
return weight;
}

public void setWeight(int weight) {
this.weight = weight;
}

public EdgeNode getNext() {
return next;
}

public void setNext(EdgeNode next) {
this.next = next;
}

}

/**
* 顶点表结点
*
*/
class VertexNode {
/**
* 顶点入度
*/
private int in;

/**
* 顶点域,存储顶点信息(下标)
*/
private int data;

/**
* 边表头指针
*/
private EdgeNode firstEdge;

public VertexNode(int in, int data, EdgeNode firstEdge) {
super();
this.in = in;
this.data = data;
this.firstEdge = firstEdge;
}

public int getIn() {
return in;
}

public void setIn(int in) {
this.in = in;
}

public int getData() {
return data;
}

public void setData(int data) {
this.data = data;
}

public EdgeNode getFirstEdge() {
return firstEdge;
}

public void setFirstEdge(EdgeNode firstEdge) {
this.firstEdge = firstEdge;
}

}
结果:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息