拓扑排序的算法

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

拓扑排序的算法的相关文章

拓扑排序(算法竞赛入门经典)

拓扑排序的定义: 把每个变量看成一个点,”小于“或者”先后“关系看成有向边,则我们得到一个有向图.这样我们的任务实际上是把一个图的所有节点排序,使每一条有向边的(u,v)对应的u都排在v之前,在图论中,我们称之为拓扑排序.不难发现,如果一个有向图里存在回路,则不存在拓扑排序(如果设置一个标志数组,我们可以发现回路中的点一直处于正在被访问状态,这可以作为拓扑排序的结束条件). 我们先看一个样例: 下面我们用邻接矩阵存储这张图:   0 1 2 3 0 0 1 1 1 1 0 0 1 1 2 0 0

拓扑排序(TopologicalSort)算法

拓扑排序算法应用: 有些事情做都需要按照流程的去做,比如你准备约你小女友去影院看速度与激情7大片,首先你想的是我怎么到达影院,然后达到影院,你可以先买票,或者等小女友来了一起买票,然后一起进电影大厅.....然后说说甜言蜜语时机成熟了有可以做下一步了:作为顶点:自己的位置,影院位置,小女友到达影院,买票,进大厅,作为顶点,比如都到达了影院买好票才可以一起进入,就是当一个顶点都被满足时才可以该顶点才可以做动作执行下一步.这是我自己的理解方式,你要还不理的话可能是我说的不够好! 1 /* 2 拓扑排

图的拓扑排序——卡恩算法

拓扑排序 有向图的拓扑排序是其顶点的线性排序,使得对于从顶点u 到顶点v 的每个有向边uv ,u 在排序中都在v 之前. 在图论中,由一个有向无环图的顶点组成的序列,当且仅当满足下列条件时,称为该图的一个拓扑排序(Topological sorting). 每个顶点出现且只出现一次: 若A在序列中排在B的前面,则在图中不存在从B到A的路径. //#include<Windows.h> #include<iostream> #include<cstring> #inclu

图基本算法 拓扑排序(基于dfs)

拓扑排序,是对有向无回路图进行排序,以期找到一个线性序列,这个线性序列在生活正可以表示某些事情完成的相应顺序.如果说所求的图有回路的话,则不可能找到这个序列. 在大学数据结构课上,我们知道求拓扑排序的一种方法.首先用一个入度数组保存每个顶点的入度.在进行拓扑排序时,我们需要找到入度为0的点,将其存入线性序列中,再将其从图中删除(与它相关的边都删除,相邻的顶点的入度均减1),再重复上面的操作,直至所有的顶点都被找到为止.如果不对每次找入度为0的顶点的方法进行处理,而直接去遍历入度数组,则该算法的时

拓扑排序之变量序列算法分析

拓扑排序之变量序列 巧若拙(欢迎转载,但请注明出处:http://blog.csdn.net/qiaoruozhuo) 题目描述: 假设有n个变量(1<=n<=26,变量名用单个小写字母表示),还有m个二元组(u,v),分别表示变量u小于v.那么,所有变量从小到大排列起来应该是什么样子的呢? 例如有4个变量a,b,c,d,若以知a<b,c<b,d<c,则这4个变量的排序可能是a<d<c<b.尽管还有可能其他的可能,你只需找出其中的一个即可. 输入: 输入为一

HDU 5638 拓扑排序+优先队列

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5638 题意: 给你一个DAG图,删除k条边,使得能个得到字典序尽可能小的拓扑排序 题解: 把拓扑排序的算法稍微改一下,如果某个顶点的入度小于k也把它加到优先队列里面去. k减小后队列里面会有些点不满足<=k,直接踢出来就好了. 代码: #include<iostream> #include<cstring> #include<cstdio> #include<

图算法之拓扑排序

拓扑排序是对有向无圈图的顶点的一种排序,它使得如果存在一条从vi到vj的路径,那么在排序中Vj出现在Vi后面.一个简单的求拓扑排序的算法是先找出任意一个没有入边的顶点,然后我们显示该顶点,并将它和它的边一起从图中删除.然后为们对图的其余部分应用同样的方法处理.但是这个方法有一点不好,就是每次都要找入度为0的顶点,这种顶点一般很少,如果图很大的话,每次都遍历一遍就浪费很多时间.升级版是先计算每一个顶点的入度,然后将入度为0的顶点存入队列,操作完之后再更新入度.这样就不用遍历整个图而只需要从出队列操

拓扑排序介绍

拓扑排序介绍 拓扑排序(Topological Order)是指,将一个有向无环图(Directed Acyclic Graph简称DAG)进行排序进而得到一个有序的线性序列. 这样说,可能理解起来比较抽象.下面通过简单的例子进行说明! 例如,一个项目包括A.B.C.D四个子部分来完成,并且A依赖于B和D,C依赖于D.现在要制定一个计划,写出A.B.C.D的执行顺序.这时,就可以利用到拓扑排序,它就是用来确定事物发生的顺序的. 在拓扑排序中,如果存在一条从顶点A到顶点B的路径,那么在排序结果中B

转:【拓扑排序详解】+【模板】

转自:http://www.cnblogs.com/skywang12345/p/3711489.html 拓扑排序介绍 拓扑排序(Topological Order)是指,将一个有向无环图(Directed Acyclic Graph简称DAG)进行排序进而得到一个有序的线性序列. 这样说,可能理解起来比较抽象.下面通过简单的例子进行说明! 例如,一个项目包括A.B.C.D四个子部分来完成,并且A依赖于B和D,C依赖于D.现在要制定一个计划,写出A.B.C.D的执行顺序.这时,就可以利用到拓扑