zoukankan      html  css  js  c++  java
  • 关键路径求解算法

    2015.8.11

    求每个活动最早发生时间,以及最晚发生时间。

    最早发生时间等于最晚发生时间的那条路径就是关键路径。

    所以,关键路径求解的关键思路在于:早发生时间,以及最晚发生时间的计算公式。

    根据公式,最早发生时间是用拓扑排序来求。

    最晚发生时间,是用倒过来的拓扑排序来求。

    关键路径求解就是这么简单。

    2016.01.11 - 2016.01.12

    关键路径求解是建立在拓扑排序基础之上的,所以需要参考之前拓扑排序的代码。

    在此基础上,更新entity:AGraph不变,ANode新添weight字段。

    邻接表的创建也相应调整:

        /**
         * create a graph of adjacency list
         */
        public void CreateAgraph(AGraph G, int A[][], int pNum)
        {
            ANode p, pre = null;
            G.setN(pNum);
            G.setE(0);
            ANode[] arr = G.getHeadNode();
            for (int i = 0; i < G.getN(); i++)
            {
                arr[i].setData(i);
                G.setHeadNode(arr);
            }
            for (int i = 0; i < G.getN(); i++)
                for (int j = 0; j < G.getN(); j++)
                    if (A[i][j] != 0)
                    {
                        p = new ANode();
                        p.setWeight(A[i][j]);
                        p.setData(j);
                        arr[j].setIn(arr[j].getIn() + 1);
                        if (null == arr[i].getNext())
                            arr[i].setNext(p);
                        else
                            pre.setNext(p);
                        pre = p;
                        G.setE(G.getE() + 1);
                    }
        }
    
        /**
         * output the graph
         */
        public void DispAGraph(AGraph g)
        {
            System.out.println("DispAGraph:");
            int i;
            ANode p;
            ANode[] arr = g.getHeadNode();
            for (i = 0; i < g.getN(); i++)
            {
                p = arr[i];
                while (p != null)
                {
                    System.out.print(p.getData() + "->");
                    p = p.getNext();
                }
                System.out.println();
            }
        }

    改造之前的拓扑排序方法,使之可用于求etv。

        /**
         * get etv by TopologySort
         */
        private List<Integer> CPTopologySort(Stack<ANode> stack, AGraph g)
        {
            int VERTEX_NUM = g.getN();
            List<Integer> etv = set0ofAllList(new ArrayList<Integer>(), VERTEX_NUM);
            ANode[] arr = g.getHeadNode();
            // this array is the record of topology sort
            Boolean[] visit = new Boolean[VERTEX_NUM];
            for (int i = 0; i < VERTEX_NUM; i++)
                visit[i] = false;
            Queue<ANode> queue = new LinkedList<ANode>();
    
            // get the nodes which's in-degree is 0 and add them to the queue
            for (int i = 0; i < VERTEX_NUM; i++)
                if (0 == arr[i].getIn())
                {
                    visit[i] = true;
                    queue.add(arr[i]);
                }
            
            System.out.println("topology sort:");
    
            while (!queue.isEmpty())
            {
                ANode temp = queue.peek();
                ANode nextNode = temp.getNext();
                while (null != nextNode)
                {
                    int where = nextNode.getData();
                    // in-degree decremented by one
                    arr[where].setIn(arr[where].getIn() - 1);
    
                    // add the nodes which's in-degree is 0 and haven't been sorted
                    // to the queue
                    if (0 == arr[where].getIn() && false == visit[where])
                    {
                        visit[where] = true;
                        queue.add(arr[where]);
                    }
    
                    if (etv.get(temp.getData()) + nextNode.getWeight() > etv
                            .get(where))
                        etv.set(where,
                                etv.get(temp.getData()) + nextNode.getWeight());
    
                    nextNode = nextNode.getNext();
                }
                ANode anode = queue.poll();
                // get out of the queue and print the data
                System.out.print(anode.getData() + " ");
                stack.push(anode);
            }
            System.out.println();
            return etv;
        }

    主体关键路径算法,调用之前的拓扑排序算法求得的etv,求ltv,并使用etv和ltv求关键路径:

        /**
         * get the critical path of AOE
         */
        @Override
        public void CriticalPath(AGraph g)
        {
            Stack<ANode> stack = new Stack<ANode>();
            List<Integer> etv = CPTopologySort(stack, g);
            outPutArrWithBlankLine(etv, "Output etv:");
            // initialize ltv
            List<Integer> ltv = setArrWithSingleValue(new ArrayList<Integer>(),
                    etv.get(etv.size() - 1),etv.size());
            // get ltv
            while (!stack.isEmpty())
            {
                ANode node = stack.pop();
                ANode nextNode = node.getNext();
                while (null != nextNode)
                {
                    int k = nextNode.getData();
                    if (ltv.get(k) - nextNode.getWeight() < ltv.get(node.getData()))
                        ltv.set(node.getData(), ltv.get(k) - nextNode.getWeight());
                    nextNode = nextNode.getNext();
                }
            }
            outPutArrWithBlankLine(ltv, "Output ltv:");
            ANode[] arr = g.getHeadNode();
            ANode pe;
            System.out.println();
            System.out.println("Output critical path:");
            /* get the critical path of AOE */
            for (int j = 0; j < g.getN(); j++)
            {
                for (pe = arr[j].getNext(); pe != null; pe = pe.getNext())
                {
                    int k = pe.getData();
                    int ete = etv.get(j);
                    int lte = ltv.get(k) - pe.getWeight();
                    if (ete == lte)
                        System.out.println("<v" + arr[j].getData() + " -v"
                                + arr[k].getData() + "> length: " + pe.getWeight());
                }
            }
        }

    一些其它的private方法:

        private List<Integer> set0ofAllList(List<Integer> list, int length)
        {
            for (int i = 0; i < length; i++)
                list.add(0);
            return list;
        }
    
        private void outPutArrWithBlankLine(List<Integer> etv, String instruction)
        {
            System.out.println();
            System.out.println(instruction + etv);
        }
    
        private List<Integer> setArrWithSingleValue(List<Integer> arr, Integer value,int size)
        {
            arr.clear();
            for (int i = 0; i < size; i++)
                arr.add(value);
            return arr;
        }

    新的测试方法:

    public class GraphTest1
    {
        public static void main(String[] args)
        {
            System.out.println("creating adjacency list...");
            int[][] array = new int[10][10];
            for (int i = 0; i < 10; i++)
                for (int j = 0; j < 10; j++)
                    array[i][j] = 0;
            array[0][1] = 3;
            array[0][2] = 4;
            array[1][3] = 5;
            array[2][3] = 8;
            array[1][4] = 6;
            array[3][4] = 3;
            array[2][5] = 7;
            array[4][7] = 4;
            array[5][7] = 6;
            array[4][6] = 9;
            array[7][8] = 5;
            array[6][9] = 2;
            array[8][9] = 3;
            AGraph agraph = new AGraph();
            ANode[] arr = new ANode[10];
            for (int j = 0; j < 10; j++)
                arr[j] = new ANode();
            agraph.setHeadNode(arr);
            GraphBasicService gbs = new GraphBasicServiceImpl();
            gbs.CreateAgraph(agraph, array, 10);
            gbs.DispAGraph(agraph);
            System.out.println("count in-degree:");
            ANode[] arr1 = agraph.getHeadNode();
            for (int i = 0; i < agraph.getN(); i++)
                System.out.print(arr1[i].getIn() + " ");
            System.out.println();
            gbs.CriticalPath(agraph);
        }
    }

    测试结果:

  • 相关阅读:
    fn project 试用之后的几个问题的解答
    fn project 扩展
    fn project 生产环境使用
    fn project 对象模型
    fn project AWS Lambda 格式 functions
    fn project 打包Function
    fn project Function files 说明
    fn project hot functions 说明
    fn project k8s 集成
    fn project 私有镜像发布
  • 原文地址:https://www.cnblogs.com/rixiang/p/4720574.html
Copyright © 2011-2022 走看看