关键路径求解算法

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

测试结果:

 

posted on 2015-08-11 11:50  J·Marcus  阅读(2230)  评论(0编辑  收藏  举报

导航