package ToPu; public class Graph { private final int MAX_VERTS = 20; private Vertex vertexList[]; private int adjMat[][]; private int nVerts; private char sortedArray[]; public 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 label){ vertexList[nVerts++] = new Vertex(label); } //添加边的方法 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_Vertex = nVerts; while(nVerts > 0){ //找到一个没有后继的节点 int currentVertex = noSuccessors(); if(currentVertex == -1){//一定是个环 System.out.println("图中有环"); return ; } //在这个数组中插入一个点 sortedArray[nVerts-1] = vertexList[currentVertex].label; //在图中删除这个点 deleteVertex(currentVertex); } System.out.println("输出拓扑排序的结果"); for(int j=0;j<orig_Vertex;j++){ System.out.print(sortedArray[j]+" "); } System.out.println(); } /** * 在这个图中删除该顶点 * @param currentVertex */ private void deleteVertex(int delVert) { //如果删除的不是数组中最后一个点,就后面的元素直接向前面移动,覆盖这个元素就行了。 if(delVert != nVerts-1){ for(int j=delVert;j < nVerts-1;j++){ vertexList[j] = vertexList[j+1]; } //从图中删除row for(int row=delVert;row<nVerts-1;row++){ moveRowUp(row,nVerts); } //从图中删除col for(int col=delVert;col<nVerts-1;col++){ moveColLeft(col,nVerts-1); } } nVerts--; } private void moveColLeft(int col, int length) { for(int row = 0;row<length;row++){ adjMat[row][col]=adjMat[row][col+1]; } } private void moveRowUp(int row, int length) { for(int col=0;col<length;col++){ adjMat[row][col] = adjMat[row+1][col]; } } /** * 这个方法是找没有后继的节点 * @return */ private int noSuccessors() { 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; } } =============================================== package ToPu; /** * 把一个图中的所有的节点排序使得每一条有向边(u,v)对应 * 的u排在v的前面, * 拓扑排序的最大用途就是判断一个有向图是不是有环。 * * 无前驱的顶点优先的拓扑排序方法 * 该方法的每一步总是输出当前无前驱(即入度为0)的顶点 * 算法描述: * NonPreFirstTopSort(G){//优先输出无前趋的顶点 while(图G中有人度为0的顶点)do{ 从G中选择一个人度为0的顶点v且输出之; 从G中删去v及其所有出边; } if(输出的顶点数目<|V(G)|) //若此条件不成立,则表示所有顶点均已输出,排序成功。 Error("G中存在有向环,排序失败!"); } 性质 1、 拓扑排序在有向无环图中才能排出有效的序列,否则能判断该有向图有环。 2、如果输入的有向图中的点,不存在入度为0的点,则该有向图存在回路 3、如果存在的入度为0的点大于一个,则该有向图肯定不存在一个可以确定的拓扑序列但并不妨碍拓扑排序 * * * * * * * */ public class Main { public static void main(String[] args) { Graph theGraph = new Graph(); theGraph.addVertex(‘A‘); theGraph.addVertex(‘B‘); theGraph.addVertex(‘C‘); theGraph.addVertex(‘D‘); theGraph.addVertex(‘E‘); theGraph.addVertex(‘F‘); theGraph.addVertex(‘G‘); theGraph.addVertex(‘H‘); //添加边 theGraph.addEdge(0, 3); theGraph.addEdge(0, 4); theGraph.addEdge(1, 4); theGraph.addEdge(2, 5); theGraph.addEdge(3, 6); theGraph.addEdge(4, 6); theGraph.addEdge(5, 7); theGraph.addEdge(6, 7); theGraph.topo(); } } ==================================== package ToPu; public class Vertex { public char label; public Vertex(char label){ this.label = label; } }
时间: 2024-10-25 23:02:32