关键路径算法之php实现

        拓扑排序主要是为解决一个工程能否顺序进行的问题,但有时我们还需要解决工程完成需要的最短时间问题。

        我们把路径上各个活动所持续的时间之和称为路径长度,从源点到汇点具有最大长度的路径叫关键路径,在关键

路径上的活动叫关键活动。

       关键路径算法基于拓扑排序算法,这里直接上代码,以后有机会再详解。

       class EdgeNode
    {
        public $adjvex;
        public $weight;
        public $next;

        public function __construct($adjvex, $weight = 0, $next = null)
        {
            $this->adjvex = $adjvex;
            $this->next = $next;
            $this->weight = $weight;
        }
    }

    class VertexNode
    {
        public $in;
        public $data;
        public $firstedge = null;

        public function __construct($in, $data, $firstedge)
        {
            $this->in = $in;
            $this->data = $data;
            $this->firstedge = $firstedge;
        }
    }

    class Graph
    {
        public $adjList;
        public $num;

        public function __construct($adjList, $num)
        {
            $this->adjList = $adjList;
            $this->num = $num;
        }
    }

    $EdgeNode0 = new EdgeNode(2, 4, new EdgeNode(1, 3));
    $EdgeNode1 = new EdgeNode(4, 6, new EdgeNode(3, 5));
    $EdgeNode2 = new EdgeNode(5, 7, new EdgeNode(3, 8));
    $EdgeNode3 = new EdgeNode(4, 3);
    $EdgeNode4 = new EdgeNode(7, 4, new EdgeNode(6, 9));
    $EdgeNode5 = new EdgeNode(7, 6);
    $EdgeNode6 = new EdgeNode(9, 2);
    $EdgeNode7 = new EdgeNode(8, 5);
    $EdgeNode8 = new EdgeNode(9, 3);
    $EdgeNode9 = null;

    $adjList = array(
        new VertexNode(0, 'V0',  $EdgeNode0),
        new VertexNode(1, 'V1',  $EdgeNode1),
        new VertexNode(1, 'V2',  $EdgeNode2),
        new VertexNode(2, 'V3',  $EdgeNode3),
        new VertexNode(2, 'V4',  $EdgeNode4),
        new VertexNode(1, 'V5',  $EdgeNode5),
        new VertexNode(1, 'V6',  $EdgeNode6),
        new VertexNode(2, 'V7',  $EdgeNode7),
        new VertexNode(1, 'V8',  $EdgeNode8),
        new VertexNode(2, 'V9',  $EdgeNode9),
    );

    $graph = new Graph($adjList, 10);

//----------------------- 第一种  ------------------------------------
    $etv = array_fill(0, 10, 0);
    $stackTop = $stackTop2 = -1;
    $count = 0;
    $stack = $stack2 = array();
    foreach ($graph->adjList as $adjKey => $adjItem) {
        if ($adjItem->in == 0) {
            $stack[++$stackTop] = $adjKey;
        }
    }

    while ($stackTop != -1) {
        $getTop = $stack[$stackTop--];
        // printf("%s -> ", $graph->adjList[$getTop]->data);
        $count += 1;
        $stack2[++$stackTop2] = $getTop;

        for ($e = $graph->adjList[$getTop]->firstedge; !empty($e); $e = $e->next) { 
            $k = $e->adjvex;
            $graph->adjList[$k]->in -= 1;
            if (!$graph->adjList[$k]->in) {
                $stack[++$stackTop] = $k;
            }
            if (($etv[$getTop] + $e->weight) > $etv[$k]) {
                $etv[$k] = $etv[$getTop] + $e->weight;
            }
        }
    }

    //关键路径
    $ltv = array_fill(0, $graph->num, $etv[$graph->num - 1]);

    while ($stackTop2 != 0) {
        $getTop = $stack2[$stackTop2--];

        for ($e = $graph->adjList[$getTop]->firstedge; !empty($e); $e = $e->next)
        {
            $k = $e->adjvex;
            if (($ltv[$k] - $e->weight) < $ltv[$getTop] ) {
                $ltv[$getTop] = $ltv[$k] - $e->weight;
            }
        }
    }

    for ($j = 0; $j < $graph->num; $j++) {
        for ($e = $graph->adjList[$j]->firstedge; !empty($e); $e = $e->next)
        {
            $k = $e->adjvex;
            $ete = $etv[$j];
            $lte = $ltv[$k] - $e->weight;
            if ($ete == $lte) {
                echo "<" . $graph->adjList[$j]->data . "," . $graph->adjList[$k]->data . "> length: " . $e->weight . " , ";
            }
        }
    }

    if ($count < $graph->num) {
        exit('不是AOV网');
    } else {
        exit('是的');
    }

发布了151 篇原创文章 · 获赞 107 · 访问量 133万+

猜你喜欢

转载自blog.csdn.net/sanbingyutuoniao123/article/details/82317009