拓补排序是将一个有向无环图中的所有顶点排成一个线性队列,使得如果从顶点a到b存在一条有向边,则顶点a在顶点b之前。一个图可能有若干个不同的拓补顺序序列,如果有向图不含有环,则至少能够找到一个这样的序列。注意,含有环的图是不可能存在拓补顺序的,如果顶点a与b在环上,就既存在从a到b的路径又存在从b到a的路径。不管a与b选择什么顺序,这些路径中的任何一条都将与之相矛盾。拓补排序有什么意义呢?拓补排序在实际生活中和算法中都有很大的应用,比如要排一下几门课程的先后次序,我们可以将课程抽象成结点,将什么课程是什么课程的基础抽象成边,那么该图的一个拓补序列,就是这些课一个可行的先后次序。

     拓补排序的思想:1)从图中选取一个入度为0的顶点,并输出之 2)从图中”删除“此顶点,并删除所有以它为目标顶点的边

     重复上述两个步骤,直至图为空或找不到入度为0的顶点为止。

     我的考虑:从图中删除顶点的话,会导致破坏原图的结构,从而导致某个图往往为了得到它的拓补排序,必须把自身破坏了(删除其顶点及相应的边),这就意味着进行完拓补排序的图就不能进行类似的比如深度优先、广度优先的搜索了。所以我决定不采用删除顶点的办法,改用是否被visited来标识。就是从图中的某个顶点来找它的前驱结点的时候,如果该顶点存在没有被访问过的前驱结点,那么该顶点的入度不为0.这也就意味着如果该顶点所有的前驱结点已经被访问过,那么该顶点的入度为0。

     代码实现思路(关于顶点前驱结点,我们可以在顶点类中加一个列表,当用户构造这个图的时候,就把这个顶点相应的前驱结点加入到列表中):

public Stack<T> getTopologicalSort() {
		// TODO Auto-generated method stub
		Stack<T> vertexStack=new Stack<T>();
		for(int i=0;i<vertices.size();i++)
		{
			VertexInterface<T> nextVertex=getZeroIndegree();
			nextVertex.visit();
			vertexStack.push(nextVertex.getLabel());
		}
		return vertexStack;
	}
    
	private VertexInterface<T> getZeroIndegree()
	{
		VertexInterface<T> result=null;
		Collection<VertexInterface<T>> mySet=vertices.values();
		Iterator<VertexInterface<T>> myIterator=mySet.iterator();  
		while(myIterator.hasNext())
		{
			VertexInterface<T> nextVertex=myIterator.next();
			if(!nextVertex.isVisited()&&!nextVertex.hasPredecessor())
			{
				result=nextVertex;
				break;
			}
		}
		return result;
	}
public boolean hasPredecessor() {
		// TODO Auto-generated method stub
	    boolean result=false;
		if(previousVertexList.size()!=0)
		{
			Iterator<VertexInterface<T>> myIterator=previousVertexList.iterator();
			while(myIterator.hasNext())
			{
				VertexInterface<T> nextVertex=myIterator.next();
				if(!nextVertex.isVisited())
				{
					   result=true;
					   break;
				}
			}
		}
		return result;
	}