所谓拓扑排序,就是对有向图构造拓扑序列的过程。
基本思路:从AOV网中选择一个入度为0的顶点输出,然后删除此顶点,并删除以此顶点为尾的弧,重复此步骤;
直到输出全部顶点或不存在入度为0的顶点为止。
1.数据结构
顶点数据结构:
public class VertexNode { private int in ; //入度 private String data; //数据域 private EdgeNode firstEdge; //指向以该顶点为起点的第一条弧 (有向图中称为弧)
//省略get,set方法}
弧的数据结构
public class EdgeNode { private int adjvex; //顶点对应数组中的位置 private int weight; //权值 网中才用到 private EdgeNode next;//指向下一条以弧,起点和该弧相同
//省略set,get方法}
图的数据结构:
public class GraphList { private VertexNode[] vertexNodes = new VertexNode[100]; //最多存放100个顶点 private int vertextNum; //顶点数 private int edgeNum; //边数
//省略set,get方法}
2.实现与测试
public class App { public static void main(String[] args){ GraphList g = createGraph(); // traverseGraph(g); topologicalSort(g); } /** * 使用邻接表创建图 * v0->v1 v0->v2 v1->v3 v2->3 v4->v3 */ private static GraphList createGraph(){ GraphList list = new GraphList(); Scanner sc = new Scanner(System.in); System.out.println("输入顶点数:"); int vertextNum = sc.nextInt(); list.setVertextNum(vertextNum); System.out.println("输入边数:"); int edgeNum = sc.nextInt(); list.setEdgeNum(edgeNum); for(int i = 0; i < list.getVertextNum(); i++){ VertexNode vertexNode = new VertexNode(); vertexNode.setData("v" + i); //顶点名称 v0,v1,.... list.getVertexNodes()[i] = vertexNode; } //起点,终点的位置必须小于顶点数 for(int i = 0; i < list.getEdgeNum(); i++){ System.out.println("请输入边(vi,vj)的起点:"); int start = sc.nextInt(); System.out.println("请输入边(vi,vj)的终点"); int end = sc.nextInt(); EdgeNode edgeNode = new EdgeNode(); edgeNode.setAdjvex(end); VertexNode vertexNode = list.getVertexNodes()[end]; vertexNode.setIn(vertexNode.getIn() + 1); //给终点对应的顶点入度 +1 //将边 按照头插法 插入到链表中 edgeNode.setNext(list.getVertexNodes()[start].getFirstEdge()); list.getVertexNodes()[start].setFirstEdge(edgeNode); } return list; } /** * 拓扑排序:对有向图构建拓扑序列的过程 * 判断是不是aov网 * * 思路:首先将入度为0的顶点入栈,然后栈, * 每出一个顶点,将与这个顶点相关的顶点(必须是终点)入度减一, * 减一之后如果入度为0则入栈, * 然后重复出队列 * */ private static void topologicalSort(GraphList g){ int count = 0; //计算输出的顶点数,如果小于图中顶点数,说明有换,不是AOV网 int top = 0; //栈队尾的位置,初始化为0 表示空队列 VertexNode[] stack = new VertexNode[100]; //此处使用顺序栈 //将入度为0的顶点加入到栈中 for(int i = 0; i < g.getVertextNum(); i++){ if(g.getVertexNodes()[i].getIn() == 0){ //如果顶点入度为0 stack[top++] = g.getVertexNodes()[i]; } } //如果栈顶指针不为0 即不是空栈 while(top != 0){ VertexNode vertexNode = stack[--top]; //出栈 System.out.println("出栈顶点为:" + vertexNode.getData()); count ++; //输出顶点数 +1 EdgeNode edgeNode = vertexNode.getFirstEdge(); while(edgeNode != null){ VertexNode linkNode = g.getVertexNodes()[edgeNode.getAdjvex()]; linkNode.setIn(linkNode.getIn() -1); if(linkNode.getIn() == 0){ stack[top++] = linkNode; } edgeNode = edgeNode.getNext(); } } if(count < g.getVertextNum()){ System.out.println("不是AOV网"); }else{ System.out.println("这是一个AOV网"); } } private static void traverseGraph(GraphList g){ for(int i = 0; i < g.getVertextNum(); i++){ System.out.println("顶点v" + i + ":"); EdgeNode edgeNode = g.getVertexNodes()[i].getFirstEdge(); while(edgeNode != null){ System.out.print("v" + edgeNode.getAdjvex() +"->"); edgeNode = edgeNode.getNext(); } System.out.println(); } } }
3.结果:
出栈顶点为:v4
出栈顶点为:v0
出栈顶点为:v1
出栈顶点为:v2
出栈顶点为:v3
这是一个AOV网
结论:只要没有回路(即环) 就是AOV网