在一个有向无回路图(AOV网,Activity On Vertex)中找到一个拓扑序列的过程称为拓扑排序。
拓扑序列:图中所有顶点沿着水平线排列而成的一个序列。
拓扑排序的实现步骤:1>从有向图中选择一个没有前驱(即入度为0)的顶点并且输出它;
2>从图中删除该结点,并且删除所有从该结点出发的弧,将这些弧头的入度减1;
3> 重复上述两步,直到所有的顶点都输出。
源码:
public class Test {
/** 图的顶点信息*/
private static char[] vertexs = {'A','B','C','D','E','F'};
/** 图的顶点的使用情况 */
private static int[] vertexStatus = {0,0,0,0,0,0};
/** 使用邻接矩阵存储图的边信息*/
private static int[][] edges = {
{0,1,1,1,0,0},
{0,0,0,0,0,0},
{0,1,0,0,1,0},
{0,0,0,0,1,1},
{0,0,0,0,0,0},
{0,0,0,0,1,0}
};
class Stack {
private int[] stackList;
private int top;
public Stack(int length) {
stackList = new int[length];
top = -1;
}
/** 入栈 */
public void push(int val) {
stackList[++top] = val;
}
/** 出栈 */
public void pop() {
--top;
}
/** 查询栈顶元素 */
public int peek() {
if (top != -1) {
return stackList[top];
}
return -1;
}
/** 判空 */
public boolean isEmpty() {
if (top == -1) {
return true;
}
return false;
}
}
public static void main(String[] args) throws Exception {
/**
* 拓扑排序的实现
* 1.获取入度为0的节点
* 2.将入度为0的节点保存到结果列表中,查找有向图中以该节点为首的边所对应的尾节点的入度减1
* 3.重复1,2
*/
int index = getInDegreeIndex();
if (index != -1) {
char[] results = new char[vertexs.length];
int resultIndex = 0;
results[resultIndex] = vertexs[index];
Test.Stack stack = new Test().new Stack(vertexs.length);
stack.push(index);
while(!stack.isEmpty()) {
updateInDegree(stack.peek());
vertexStatus[stack.peek()] = 1;
stack.pop();
index = getInDegreeIndex();
if (index != -1) {
stack.push(index);
results[++resultIndex] = vertexs[index];
}
}
StringBuffer sb = new StringBuffer();
for (int i = 0; i < results.length; i++) {
sb.append(results[i]);
if (i != results.length - 1) {
sb.append(",");
}
}
System.out.println(sb);
} else {
System.out.println("该图存在环,不能进行拓扑排序!");
}
}
/** 获取入度为0的结点下标索引*/
private static int getInDegreeIndex () {
int index = -1;
int row = edges.length;
int col = edges[0].length;
for (int i = 0; i < col;i++) {
if (vertexStatus[i] == 0) {
for (int j = 0; j < row; j++) {
index = i;
if (edges[j][i] != 0) {
index = -1;
break;
}
}
if (index != -1) {
return index;
}
}
}
return index;
}
/** 入度减1操作*/
private static void updateInDegree (int index) {
int col = edges.length;
for (int i = 0; i < col;i++) {
if (edges[index][i] != 0) {
edges[index][i]--;
}
}
}
}
运行结果:A,C,B,D,F,E
来源:CSDN
作者:等待中的小码农
链接:https://blog.csdn.net/zhangting19921121/article/details/104302634