拓扑排序

Assume that we need to schedule a series of tasks, such as classes or construction jobs, where we cannot start one task until after its prerequisites are completed. We wish to organize the tasks into a linear order that allows us to complete them one at a time without violating any prerequisites. We can model the problem using a DAG(有向无环图).The graph is directed because one task is a prerequisite of another. The process of laying out the vertices of a DAG in a linear order to meet the prerequisite rules is called a topological sort

拓扑排序解决的是一系列相互依赖的事件的排序问题,拓扑排序算法的结果很可能有多个,拓扑排序为线性排序,效率为O(|V|+|E|),其中|V|表示顶点数,|E|表示边的数量


拓扑排序满足的条件:

  1. 每个顶点出现且只出现一次;

  2. 若A在序列中排在B的前面,则在图中不存在从B到A的路径

拓扑排序是对有向无环图的顶点的一种排序,它使得如果存在一条从顶点A到顶点B的路径,那么在排序中B出现在A的后面


如图所示有向无环图

拓扑排序

其拓扑排序序列为J1,J3,J2,J6,J4,J5,J7  OR   J1,J2,J3,J6,J4,J5,J7


算法思路:

使用队列实现拓扑排序

  1. 首先访问所有的边,计算指向每个顶点的边数(即计算每个顶点先决条件的数目)

  2. 将所有没有先决条件的顶点放入队列,当从队列中删除一个顶点的时候,将其所有相邻顶点的先决条件计数减去1

  3. 当某个相邻顶点计数是0,就将其放入队列。

  4. 重复2-3直到队列为空

static void topsort(Graph G) { // Topological sort: Queue
		Queue<Integer> Q = new AQueue<Integer>(G.n());
		int[] Count = new int[G.n()];
		int v;
		for (v = 0; v < G.n(); v++)
			Count[v] = 0; // Initialize
		for (v = 0; v < G.n(); v++)
			// Process every edge
			for (int w = G.first(v); w < G.n(); w = G.next(v, w))
				Count[w]++; // Add to v’s prereq count
		for (v = 0; v < G.n(); v++)
			// Initialize Queue
			if (Count[v] == 0) // V has no prerequisites
				Q.enqueue(v);
		while (Q.length() > 0) { // Process the vertices
			v = Q.dequeue().intValue();
			printout(v); // PreVisit for Vertex V
			for (int w = G.first(v); w < G.n(); w = G.next(v, w)) {
				Count[w]--; // One less prerequisite
				if (Count[w] == 0) // This vertex is now free
					Q.enqueue(w);
			}
		}
	}


你可能感兴趣的:(java,图,拓扑排序)