关键路径 java

原理

关键路径是指设计中从输入到输出经过的延时最长的逻辑路径。优化关键路径是一种提高设计工作速度的有效方法。一般地,从输入到输出的延时取决于信号所经过的延时最大路径,而与其他延时小的路径无关。

理解

关键路径就是从起始点到终点需要花费时间最多的路径

关键路径定义

这里写的是一些关于关键路径的定义

ve: 事件最早开始时间(点的最早开始时间)
vl: 事件最迟开始时间(点的最后开始时间)
ee: 活动最早开始时间(边的最早开始时间)
el: 活动最迟开始时间(边的最迟开始时间)

关键事件 : ve == vl
关键活动 : el == ee

ve: 事件最早开始时间是由拓扑排序得到
其实最核心的是 如果一个节点有入度 那么该点的最早开始时间 由入度 的源点的的最早开始时间 + 边长度 其实是一个迭代 (如果有多个,那么取出最大时间)(最开始的是0)
vl: 事件最迟开始时间是指拓扑排序的逆序得到
其实最核心的是 如果一个节点有出度 那么该点的最迟开始时间 是由出度的边的目标节点的最迟开始时间 - 边的权值 (如果有多个,那么取出最小的时间) (最开始的默认值:终点的最早开始时间)
ee: 活动最早开始时间
活动的最早开始时间,是由点的出度的 事件的最早开始事件决定的。
el: 活动最迟开始时间
活动的最迟开始时间,是由边的终点的最迟时间开始 - 边的权值

代码

package com.company;

import java.util.*;

class AoeNode{
    String name;
    ArcAoeNode firstArc;

    public AoeNode(String name) {
        this.name = name;
    }
}
class ArcAoeNode{
    int nextNode;
    int weight;
    String name;
    ArcAoeNode nextArc;

    public ArcAoeNode(int nextNode, int weight,String name) {
        this.nextNode = nextNode;
        this.weight = weight;
        this.name = name;
    }
}
public class CriticalPath {
    List<AoeNode> aoeNodes;
    List<ArcAoeNode> arcAoeNodes;
    /** ve 事件最早发生时间 */
    int[] ve;
    /** vl 事件最晚发生时间 */
    int[] vl;
    /** ee 活动最早发生时间 */
    int[] ee;
    /** el 活动最晚发生时间 */
    int[] el;
    /** 遍历的stack */
    Stack<Integer> viewStack = new Stack<>();
    public CriticalPath(List<AoeNode> aoeNodes) {
        this.aoeNodes = aoeNodes;
        ve = new int[aoeNodes.size()];
        vl = new int[aoeNodes.size()];
        getAllArc();
        ee = new int[arcAoeNodes.size()];
        el = new int[arcAoeNodes.size()];

    }
    public void getAllArc(){
        arcAoeNodes = new ArrayList<>();
        for(AoeNode aoeNode: aoeNodes){
            for(ArcAoeNode arcAoeNode=aoeNode.firstArc;arcAoeNode!=null;arcAoeNode=arcAoeNode.nextArc){
                arcAoeNodes.add(arcAoeNode);
            }
        }
    }
    public int getin(int nodeIndex){
        int countIn=0;
        for(AoeNode aoe: aoeNodes){
            ArcAoeNode arcAoeNode = aoe.firstArc;
            while (arcAoeNode!=null){
                if(arcAoeNode.nextNode == nodeIndex ){
                    countIn+=1;
                }
                arcAoeNode = arcAoeNode.nextArc;
            }
        }
        return countIn;
    }

    // topologic
    public boolean topologic(){

        Queue<Integer> queue = new LinkedList<>();
        int[] book = new int[aoeNodes.size()];
        // init
        for(int i = 0; i< aoeNodes.size(); i++){
            book[i] = getin(i);
            if(book[i]==0){
                queue.offer(i);
            }
        }
        int visitLen = 0;
        while (!queue.isEmpty()){
            int poll = queue.poll();
            viewStack.push(poll);
            visitLen++;
            ArcAoeNode arcAoeNode = aoeNodes.get(poll).firstArc;
            while (arcAoeNode!=null){
                int node = arcAoeNode.nextNode;
                ve[node] = Math.max(ve[node],ve[poll]+ arcAoeNode.weight );
                book[node]--;
                if(book[node]==0){
                    queue.offer(node);
                }
                arcAoeNode = arcAoeNode.nextArc;
            }
        }
        return visitLen== aoeNodes.size();
    }
    public void criticalPath(){
        if(!topologic()){
            System.out.println("是个环装图,没有关键路径");
            return;
        }

        // vl
        // vl init
        for(int i=0;i<ve.length;i++){
            vl[i] = ve[ve.length-1];
        }
        while (!viewStack.isEmpty()){
            int popValue = viewStack.pop();
            ArcAoeNode arcAoeNode = aoeNodes.get(popValue).firstArc;
            while (arcAoeNode!=null){
                int nextNode = arcAoeNode.nextNode;
                vl[popValue] = Math.min(vl[popValue],vl[nextNode]-arcAoeNode.weight);
                arcAoeNode = arcAoeNode.nextArc;
            }
        }

        // el ee
        int arcCount = 0;
        for(int i=0;i<aoeNodes.size();i++){
            ArcAoeNode arcAoeNode = aoeNodes.get(i).firstArc;
            while (arcAoeNode!=null){
                int nextNode = arcAoeNode.nextNode;
                ee[arcCount]=ve[i];
                el[arcCount]=vl[nextNode]-arcAoeNode.weight;
                arcCount++;
                arcAoeNode = arcAoeNode.nextArc;
            }
        }
        // 关键事件
        System.out.println("关键事件");
        for(int i=0;i<aoeNodes.size();i++){
            if(vl[i]==ve[i]){
                System.out.println(aoeNodes.get(i).name);
            }
        }
        // 关键活动
        System.out.println("关键活动");
        for(int i=0;i<ee.length;i++){
            if(ee[i]==el[i]){
                System.out.println(arcAoeNodes.get(i).name);
            }
        }

    }


}
class testCriticalPath{
    public static void main(String[] args) {
        List<AoeNode> list = new ArrayList<>();
        // 加人点
        for(int i=0;i<10;i++){
            list.add(new AoeNode("V"+i));
        }
        // 加入边
        // v0
        AoeNode aoeNode = list.get(0);
        aoeNode.firstArc = new ArcAoeNode(1,3,"a0");
        aoeNode.firstArc.nextArc = new ArcAoeNode(2,4,"a1");
        // v1
        aoeNode = list.get(1);
        aoeNode.firstArc = new ArcAoeNode(3,5,"a2");
        aoeNode.firstArc.nextArc = new ArcAoeNode(4,6,"a3");
        // v2
        aoeNode = list.get(2);
        aoeNode.firstArc = new ArcAoeNode(3,8,"a4");
        aoeNode.firstArc.nextArc = new ArcAoeNode(5,7,"a5");
        // v3
        aoeNode = list.get(3);
        aoeNode.firstArc = new ArcAoeNode(4,3,"a6");
        // v4
        aoeNode = list.get(4);
        aoeNode.firstArc = new ArcAoeNode(6,9,"a7");
        aoeNode.firstArc.nextArc = new ArcAoeNode(7,4,"a8");
        // v5
        aoeNode = list.get(5);
        aoeNode.firstArc = new ArcAoeNode(7,6,"a9");
        // v6
        aoeNode = list.get(6);
        aoeNode.firstArc = new ArcAoeNode(9,2,"a10");
        // v7
        aoeNode = list.get(7);
        aoeNode.firstArc = new ArcAoeNode(8,5,"a11");
        // v8
        aoeNode = list.get(8);
        aoeNode.firstArc = new ArcAoeNode(9,3,"a12");
        // 图的完成
        CriticalPath criticalPath = new CriticalPath(list);
        criticalPath.criticalPath();

    }
}

posted @   度一川  阅读(453)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
点击右上角即可分享
微信分享提示