拓扑排序--关键路径实现

本文是图论算法的补充, 详见我另一篇博客  图的算法

截止目前 我是实现了 最小生成树,最短路径,遍历,拓扑排序和关键路径算法。 一再强调 图上的算法不依赖于图的具体实现,我给出了邻接矩阵和邻接表上的实现作为参考

开始之前,回顾一下上期我们定义在图上的API

package lee.graph;

import java.io.FileNotFoundException;
public interface Graph {
	public void initGraph(String path) throws FileNotFoundException;
	public int getWeight(int v , int w);
	public int getFirstNeighbor(int v);
	public int getNextNeighbor(int v, int w);
	public void setWeight(int v, int w , int power);
	public void printGraph();
	public int getNumVertex();
	public int getNumEdge();
	public int getOutDegree(int v);
	public int getInDegree(int v);
	public int getFirstPro(int v);
	public int getNextPro(int v,  int w);
	
}

getFirstPro(v);
getNextPro(v, w)
是这一期增加的, 其作用后面阐述。

拓扑排序:

	public static int[] topologicalSort(Graph g){
		int[] inDegree = new int[g.getNumVertex()];
		int [] sortResult = new int[g.getNumVertex()];
		int count = 0 ;
		Stack<Integer> stack1 = new ArrayStack<Integer>();
		Stack<Integer> stack2 = new LinkedStack<Integer>();
		
		for(int i=0; i<g.getNumVertex();i++){
			inDegree[i] = g.getInDegree(i);
			if(inDegree[i]==0){
				stack1.push(i);
			}
		}
		
		while(stack1.isEmpty()){
			int v = stack1.pop();
			stack2.push(v);
			sortResult[count++] = v;
			int w = g.getFirstNeighbor(v);
			while(w!=-1){
				inDegree[w]--;
				if(inDegree[w]==0){
					stack1.push(w);
				}
				w = g.getNextNeighbor(v, w);
			}
		}	
		if(count != g.getNumVertex()){
			System.out.println("This is circle in the graph!!!");
		}
		return sortResult;
	}


关键路径:

	public static void criticalPaht(Graph g){
		int[] inDegree = new int[g.getNumVertex()];
		//Stack<Integer> stack1 = new ArrayStack<Integer>();
		Queue<Integer> queue = new CircleQueue<Integer>();
		Stack<Integer> stack2 = new LinkedStack<Integer>();
		int[] etv = new int[g.getNumVertex()];
		for(int i=0; i<g.getNumVertex();i++){
			etv[i] = 0;
			inDegree[i] = g.getInDegree(i);
			if(g.getInDegree(i)==0){
				queue.enQuene(i);
			}
		}
		int count=0;
		while(!queue.isEmpty()){
			int v = queue.deQueue();
			count++;
			stack2.push(v);
			for(int w = g.getFirstNeighbor(v); w!=-1;w = g.getNextNeighbor(v, w)){
				//inDegree[w]--;
				if(--inDegree[w]==0){
					queue.enQuene(w);
				}
				if(etv[v]+g.getWeight(v, w)>etv[w]){
					etv[w]=etv[v]+g.getWeight(v, w);
				}
			}
		}
		if(count!=g.getNumVertex()){
			System.out.println("This is circle in the graph!!!");
			System.out.println(count);
		}
		//-------------------------------------------------------------------
		int[] ltv = new int[g.getNumVertex()];
		for(int i=0; i<g.getNumVertex();i++){
			ltv[i] = etv[g.getNumVertex()-1];
		}
		
		while(!stack2.isEmpty()){
			int v = stack2.pop();
			for(int w = g.getFirstPro(v);w!=-1;w=g.getNextPro(v, w)){
				if(ltv[v]-g.getWeight(w, v) < ltv[w]){
					ltv[w]=ltv[v]-g.getWeight(w, v);
				}
			}
		}
		//-----------------------out put the critical Path---------------------------
		for(int i=0;i<g.getNumVertex();i++){
			for(int w=g.getFirstNeighbor(i); w!=-1; w=g.getNextNeighbor(i, w)){
				//System.out.println("    w="+w);
				if(etv[i] == ltv[w]-g.getWeight(i, w)){
					System.out.println(i + "->" + w);
				}
			}
		}
	}
	


关键路径算法  前面部分是拓扑排序算法。  为了好玩, 我在关键路径算法中用 队列替换了工作栈。

getFirstPro(v);
getNextPro(v, w)
这一对方法很奇怪吧。

getFirstPro(v);
其实是有向图v节点的第一个前驱节点

同理

getNextPro(v, w)
是v节点对相对w节点的下一个前驱节点。 

Matrix实现的图还好。 邻接表实现,如果没有逆邻接表,时间复杂度对会上来。我就没有写逆邻接表。曾经认为逆邻接表没啥用。图大了还是需要空间换取时间的

在Matrix上的实现

@Override
    public int getFirstPro(int v) {
        for(int i=0; i<numVertex;i++){
            if(matrix[i][v]!=999 && i!=v){
                return i;
            }
        }
        return -1;
    }

    @Override
    public int getNextPro(int v, int w) {
        for(int i=w+1; i<numVertex;i++){
            if(matrix[i][v]!=999 && v!=i){
                return i;
            }
        }
        return -1;
    }

邻接表上的实现:

public int getFirstPro(int v) {
		for(int i=0;i<numVertex;i++){
			GNode p = arr[i].next;
			while(p!=null){
				if(p.num == v){
					return i;
				}                              
                                 p=p.next;  //  更正
			}
		}
		return -1;
	}
	@Override

	public int getNextPro(int v, int w) {
		for(int i=w+1;i<numVertex;i++){
			GNode p = arr[i].next;
			while(p!=null){
				if(p.num == v){
					return i;
				}
                         p=p.next;//  更正

			}
		}
		return -1;
	}

这些代码是 上一篇 图上算法的一部分。 可以拷贝到GraphAlgorithms中运行, 所用栈,队列,堆等工具是我自己写的。 如果要运行需要调用JAVA提供的库,或者自己实现。

我的工具类实现可以参考blog中的 工具类实现篇


测试数据:

0 1 3
0 2 4
1 4 6
1 3 5
2 3 8
2 5 7
3 4 3
4 6 9
4 7 4
5 7 6
6 9 2
7 8 5
8 9 3


执行结果:
0->2
2->3
3->4
4->7
7->8
8->9


评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值