1. 程式人生 > >最小生成樹演算法普利姆演算法和克魯斯卡爾演算法實現

最小生成樹演算法普利姆演算法和克魯斯卡爾演算法實現

最小生成樹演算法:
普里姆演算法:頂點集合N,輔助頂點集合S,初始化中,將出發點vi加入S,並從N中刪除
1.從頂點集合N中找到一條到集合S最近的邊(vi,vj),儲存該邊,並將vj從N移到S中
2.重複1步驟直至所有頂點加入S集合
普里姆演算法:與邊的多少關係不大,適合計算邊稠密的圖

克魯斯卡爾演算法:將圖中的N個訂單分成Ni個點集合,T是邊集合,TE是最小生成樹的邊集合。
1.從T中找出一條最短的邊,這條邊是連線兩個不同集合的邊
2.將該邊的頂點所在的集合合併成一個集合,將邊的兩點和值記錄到TE中
3.從T中刪除該邊
4.重複步驟1-3,知道所有頂點合併成一個集合

程式碼實現:

/**
     * @name 最小生成樹普利姆演算法
     * @use 使用普利姆演算法計算圖的最小生成樹,圖用矩陣(二維陣列)表示
     * @param chart 圖矩陣
     * @param poin 起始點
     * @return 最小生成樹集合
     */
    public static function mainTreePrim($chart, $point) 
    {
        $minTree = array();
        $S = array($point);//包含點集合的集合
        while (count($S) < count($chart)) {
            $min = PHP_INT_MAX;
            $x = 0;
            $y = 0;
            foreach ($chart as $key1 => $value1) {
                if (in_array($key1,$S)) {
                    continue;
                }
                foreach ($S as $value2) {
                    if ($chart[$value2][$key1] != 0 && $chart[$value2][$key1] < $min) {
                        $min = $chart[$value2][$key1];
                        $x = $value2;
                        $y = $key1;
                    }
                }

            }
            $minTree[] = array('start' => $x, 'end' => $y);
            $S[] = $y;
        }
        return $minTree;
    }
    /**
     * @name 最小生成樹克魯斯卡爾演算法
     * @use 使用克魯斯卡爾演算法計算圖的最小生成樹,圖用矩陣(二維陣列)表示
     * @param chart 圖矩陣
     * @param poin 起始點
     * @return 最小生成樹集合
     */
    public static function mainTreeKruskal($chart, $point) 
    {
        $T = array();//未訪問的邊
        $TE = array();//已訪問的邊
        $nodes = array(array($point));
        foreach ($chart as $key1 => $value1) {
            foreach ($value1 as $key2 => $value2) {
                if ($value2 != 0) {
                    $T[] = array('x' => $key1, 'y' => $key2, 'value' => $value2);
                }
            }
        }
        while ($T) {
            $min = PHP_INT_MAX;
            $slide = array();
            $tempKey = 0;
            foreach ($T as $key => $value) {
                if ($value['value'] < $min) {
                    $min = $value['value'];
                    $slide = $value;
                    $tempKey = $key;
                }
            }
            $set1 = -1;
            $set2 = -1;
            foreach ($nodes as $key => $value) {
                if (in_array($slide['x'],$value)) {
                    $set1 = $key;
                }
                if (in_array($slide['y'],$value)) {
                    $set2 = $key;
                }
            }
            unset($T[$tempKey]);
            if ($set1 !== -1 && $set1 === $set2) {
                continue;
            }
            if ($set1 === -1 && $set2 === -1){
                $nodes[] = array($slide['x'],$slide['y']);
            } else if ($set1 === -1) {
                $nodes[$set2][] = $slide['x'];
            } else if ($set2 === -1) {
                $nodes[$set1][] = $slide['y'];
            } else {
                $nodes[$set1] = array_merge($nodes[$set1],$nodes[$set2]);
                unset($nodes[$set2]);
            }
            $TE[] = $slide;
        }
        return $TE;
    }