拓扑排序的实现(Java)

    拓扑排序是图数据结构的一种操作,他可以表示一些事情可以按照一定的先后顺序执行的算法。在这种图中,需要边是有方向的,就是它构成的图就是有向图,在有向图中,顶点只能沿着指定的方向移动,如下图所示,就是一个简单的有向图。

    另外在使用邻接矩阵表示时,与无向图的表示也是有区别的,因为它的边是单向的,所以一条边在邻接矩阵中的表示只有一项。

    有向图的拓扑排序可以用在如下的场合,在数据结构与算法中文(Java)一书中,提到大学生选课的问题,大学生不能随心所欲的选择课程,因为有一些课程有先修课程,就是说这些课程必须先学习,修够了必要的课程也是取得相关专业学位的“先决条件”,为了得到学位,必须完成高级研讨会课程和比较文学课程,但是如果不选择高等代数与解析几何,就不能修高级研讨会,同样的,不修英文写作,也不能选择比较文学课程,同时要修几何,以便学习解析几何,以及修代数,以便学习高等数学和解析几何。下图表示了这样的关系。

按照课程与学位先后顺序,可以得到这样的一个排序:

BAEDGCFH,

实际上,我们可以先修英文写作(C)和比较文学(F),再修几何(B)与代数(A)那么可以得到这样的一个顺序:

CFBAEDGH

拓扑排序的思想很简单,有两个步骤是必须的:

1、找到一个没有后继的顶点。

2、从图中删除这个顶点,在列表的前面插入顶点的标记。

    重复上述1和2两个步骤,直到所有的顶点都从图中删除,这时候,列表显示的顶点顺序就是拓扑排序的结果。这里的后继也是一些顶点,它与当前节点是通过一条边相连,而且边的方向是指向后继顶点的,在图中,有一条边是从A指向D,我们说D是A的后继。后继可以有多个,也可以没有,在上边的图中,只有H顶点是没有后继的。

    拓扑排序能够处理的图,要求是没有环的,所谓的环就是路径的起点和终点都是同一个顶点,这样就形成了一个环。不包含环的图又叫树,这是一种特殊意义的树,有向无环这样的图,又叫有向无环图directed acyclic graph,缩写为DAG。

    拓扑排序中最重要的就是删除无后继的顶点,最先删除的节点,存放在排序数组的最后面。然后依次存放图中没有后继的顶点,直到图中没有顶点。

下面给出拓扑排序的代码:

Vertex.java

package com.xxx.algorithm.wh.topgraph;
public class Vertex {
	public char label;
	public Vertex(char label){
		this.label = label;
	}
}

Graph.java

package com.xxx.algorithm.wh.topgraph;

public class Graph {

	private final int MAX_VERTS=20;
	private Vertex vertList[];
	private int adjMat[][];
	private int nVerts;
	private char sortedArray[];
	
	public Graph(){
		vertList= new Vertex[MAX_VERTS];
		adjMat = new int[MAX_VERTS][MAX_VERTS];
		nVerts = 0;
		for(int i=0;i<MAX_VERTS;i++){
			for(int j=0;j<MAX_VERTS;j++){
				adjMat[i][j] = 0;
			}
		}
		sortedArray = new char[MAX_VERTS];
	}

	public void addVertex(char label){
		vertList[nVerts++] = new Vertex(label);
	}
	
	public void addEdge(int start,int end){
		adjMat[start][end] = 1;
	}
	
	public void displayVertex(int v){
		System.out.print(vertList[v].label+" ");
	}
	
	public void topo(){
		int orig_nVerts = nVerts;
		while(nVerts>0){
			int currentVertex = noSuccessors();
			if(currentVertex==-1){
				System.out.println("error:graph has cycles");
				return;
			}
			sortedArray[nVerts-1] = vertList[currentVertex].label;
			deleteVertex(currentVertex);
		}
		
		System.out.print("topologically sorted order : ");
		for(int i=0;i<orig_nVerts;i++){
			System.out.print(sortedArray[i]);
		}
		System.out.println();
	}
	
	private void moveRowUp(int row,int length){
		for(int col=0;col<length;col++){
			adjMat[row][col] = adjMat[row+1][col];
		}
	}
	
	private void moveColLeft(int col,int length){
		for(int row=0;row<length;row++){
			adjMat[row][col] = adjMat[row][col+1];
		}
	}
	
	public void deleteVertex(int delVert){
		if(delVert != (nVerts-1)){
			for(int i=delVert;i<nVerts-1;i++){
				vertList[i] = vertList[i+1];
			}
			
			for(int row=delVert;row<nVerts-1;row++){
				moveRowUp(row, nVerts);
			}
			
			for(int col=delVert;col<nVerts-1;col++){
				moveColLeft(col, nVerts-1);
			}
		}
		nVerts--;
	}
	
	public 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;
	}
	
	public static void main(String[] args) {
		Graph graph = new Graph();
		graph.addVertex('A');
		graph.addVertex('B');
		graph.addVertex('C');
		graph.addVertex('D');
		graph.addVertex('E');
		graph.addVertex('F');
		graph.addVertex('G');
		graph.addVertex('H');
		
		graph.addEdge(0, 3);
		graph.addEdge(0, 4);
		graph.addEdge(1, 4);
		graph.addEdge(2, 5);
		graph.addEdge(3, 6);
		graph.addEdge(4, 6);
		graph.addEdge(5, 7);
		graph.addEdge(6, 7);
		
		graph.topo();
				
	}

}

运行程序,打印信息如下:

topologically sorted order : BAEDGCFH

这个排序顺序也是我们前面提到的一种顺序。就是先修几何,然后修英文写作,最后获得学位,满足条件。

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

luffy5459

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值