1. 程式人生 > >貪心演算法——Prim最小生成樹

貪心演算法——Prim最小生成樹

1、首先介紹一下什麼是貪心演算法:

貪心演算法(又稱貪婪演算法)是指,在對問題求時,總是做出在當前看來是最好的選擇。也就是說,不從整體最優上加以考慮,他所做出的是在某種意義上的區域性最優解。ps:不懂得話可以百度百科,仔細瞭解。

2、prim演算法的原理:

從連通網N={V,E}中的某一頂點U0出發,選擇與它關聯的具有最小權值的邊(U0,v),將其頂點加入到生成樹的頂點

集合U中。以後每一步從一個頂點在U中,而另一個頂點不在U中的各條邊中選擇權值最小的邊(u,v),把它的頂點

加入到集合U中。如此繼續下去,直到網中的所有頂點都加入到生成樹頂點集合U中為止。

3、

Prim演算法

設G=(V,E)是連通帶權圖,V={1,2,…,n}。構造G的最小生成樹的Prim演算法的基本思想是:

(1)置S={1}

(2)只要S是V的真子集,就作如下的貪心選擇

選取滿足條件i ∈ S,j ∈ V-S,且c[i][j]最小的邊,將頂點j新增到S中。

一直到S=V時為止。

(3)選取到的所有邊恰好構成G的一棵最小生成樹。


程式碼:

#include <iostream>
#include <vector>
#include <limits>
using namespace std ;

class TreeNode//定義一個最小生成樹類
{
public:
    int m_firstNode;
    int m_lastNode ;
    int m_Value ;
    TreeNode (int firstNode= 0, int lastNode = 0, int Value = 0)
        {
            m_firstNode=firstNode;
            m_lastNode =lastNode;
            m_Value =Value;
        }
};

class Prim //定義一個Prim演算法的類
{
private:
    vector<vector<int> > m_nvvalues ; //無向連通圖
    vector<TreeNode> MinTree ;    //最小生成樹
    int NodeCount; //無相連通圖的結點數
public:
    Prim (const vector<vector<int> >& vnvalues)
    {
        m_nvvalues = vnvalues ;
        NodeCount = (int)m_nvvalues.size () ;
    }
    void DoPrim ()
    {
        // 是否被訪問標誌
        vector<bool> bFlag (NodeCount, false) ;
        bFlag[0]=true ;
        int firstNode ;
        int lastNode;
        int k=0 ;
        while(k<NodeCount-1)
        {
            //voctor<int>的最大值,也是預設值
            int nMaxWeight=numeric_limits<int>::max () ;
            // 找到當前最短路徑
            int i = 0 ;
            while (i<NodeCount)
            {
                if(!bFlag[i])
                {
                    ++ i ;
                    continue ;
                }
                for (int j = 0; j < NodeCount; ++ j)
                {
                    if (!bFlag[j] && nMaxWeight > m_nvvalues[i][j])
                    {
                        nMaxWeight = m_nvvalues[i][j] ;
                        firstNode = i ;
                        lastNode = j ;
                    }
                }
                ++ i ;
            }
            bFlag[lastNode] = true ;
            MinTree.push_back (TreeNode(firstNode, lastNode, nMaxWeight)) ;
            ++k ;
        }
        // 輸出結果
        for (vector<TreeNode>::const_iterator ite = MinTree.begin() ;
                ite != MinTree.end() ;
                ++ ite )
        {
            cout << (*ite).m_firstNode+1 << "->"
                 << (*ite).m_lastNode+1<< " : "
                 << (*ite).m_Value << endl ;
        }
    }
} ;

int main()
{
    const int NodeCount=6 ;//定義結點個數
    vector<vector<int> > values(NodeCount);//定義一個二維容器用來儲存連通圖
    for(size_t i=0;i<values.size();++i)//重定義容器的大小
    {
        values[i].resize(NodeCount,numeric_limits<int>::max()) ;
    }
    //將連通圖中的權值賦值
    values[0][1] = 6 ;
    values[0][2] = 1 ;
    values[0][3] = 5 ;
    values[1][0] = 6 ;
    values[1][2] = 5 ;
    values[1][4] = 3 ;
    values[2][0] = 1 ;
    values[2][1] = 5 ;
    values[2][3] = 5 ;
    values[2][4] = 6 ;
    values[2][5] = 4 ;
    values[3][0] = 5 ;
    values[3][2] = 5 ;
    values[3][5] = 2 ;
    values[4][1] = 3 ;
    values[4][2] = 6 ;
    values[4][5] = 6 ;
    values[5][2] = 4 ;
    values[5][3] = 2 ;
    values[5][4] = 6 ;
//定義一個prim類的物件
    Prim prim1(values) ;
//使用prim類的DoPrim方法實現Prim演算法
    prim1.DoPrim () ;
    return 0 ;
}