• 关键路径求解算法


    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);
        }
    }

    测试结果:

  • 相关阅读:
    django在admin后台注册自己创建的数据库表
    django的缓存机制
    python中eval函数作用
    falsk之文件上传
    django请求的生命周期
    mongodb高级操作
    mongodb基本操作
    mongodb安装教程
    flask之jinjia2模板(二)
    Maven系列--"maven-compiler-plugin"的使用、Maven之Surefire插件
  • 原文地址:https://www.cnblogs.com/rixiang/p/4720574.html
Copyright © 2020-2023  润新知