Prim算法(最小生成树)

问题引入:
假设我们要设计一个电子电路,我们常常需要将多个组件的针脚连接在一起。要连接n个针脚,可以用n-1根连线,每跟连线,连接两个针脚。很显然,我们希望所用连线的长度最短。
可以把上述的连线问题用一个连通的无向图来表示 G=(V,E) ,V是针脚即点的集合,E是针脚之间可能的连接(边的集合),并且对于每条边 (u,v)E ,我们赋予它权重 w(u,v) 作为连接针脚u和针脚v的代价(连线的长度),我们希望找到一个无环的子集 TE ,能够将所有节点(针脚)连接起来,又具备最小的权重,即

w(T)=(u,v)Tw(u,v)
的值最小。因为图是无环的,又连通了所有的顶点,所以T必然是一棵树,这样的树我们就成为最小生成树。
Prim算法是解决最小生成树的一种方法,属于贪心算法。具体思想是,从1个根节点R出发( RA ),一直长大到覆盖V中所有的顶点为止,算法每一步在连接集合A和A之外的所有边中,选择一条轻量级边加入到A中,算法终止时,A中的边形成一个最小生成树。
下面给出我个人的一个实现代码:

#include <iostream>
#define INIFY 65533
#define ROW 9
#define COL 9
class Prim{
    private:
        int Array[ROW][COL];    
    public:
        void CreateGraphy(){
            int i,j,k,EdgeNumbers;
            std::cout<<"输入边的数量: "<<std::endl;
            std::cin>>EdgeNumbers;
            //初始化 
            for(int i=0;i<ROW;i++)
                for(int j=0;j<COL;j++)
                    Array[i][j]=INIFY;
            //建立邻接关系 
            std::cout<<"请输入顶点的邻接关系及权重: "<<std::endl;
            while(EdgeNumbers--){
                std::cin>>i>>j>>k;
                //无向图 
                Array[i][j]=k;
                Array[j][i]=k;
            }
        }
        void PrimAlgorithm(){
            int VertexNumber=ROW;
            int i,j,k,Min;
            int lowcost[VertexNumber],Adj[VertexNumber];
            //初始化根节点 
            lowcost[0]=0,Adj[0]=0;
            std::cout<<"最小生成树的边为: "<<std::endl;

            for(int i=1;i<VertexNumber;i++){
                lowcost[i]=Array[0][i];
                Adj[i]=0;
            }
            for (i = 1; i <VertexNumber; i++){
                Min =INIFY; /* 初始化最小权值为∞, */

                j = 1;
                k = 0;

            //在当前状况下 找到最小权重值 
            while(j<VertexNumber){
                if (lowcost[j] != 0 && lowcost[j] < Min){
                    Min = lowcost[j];
                    k = j;
                }

                j++;
            }

            std::cout << "(" <<Adj[k] << ", " << k << ")" << "  "; /*打印当前边中权重最小的边,贪心的体现*/
            lowcost[k] = 0;/* 置为0 说明已经处理过*/

            for(j=1; j<VertexNumber; j++){
                if (lowcost[j] != 0 && Array[k][j]<lowcost[j]){
                    lowcost[j]=Array[k][j];/* 将较小的权值存入lowcost相应位置 */
                    Adj[j]=k;/* 将下标为k的顶点存入Adj */
                }
            }
        }   
        std::cout<<std::endl;
}

};
int main(void){
    Prim ivec;
    ivec.CreateGraphy();
    ivec.PrimAlgorithm();
    return 0;
}

测试用例为算法导论中讲prim算法时的测试用例。
这里写图片描述
这里写图片描述
其中a b c d e f g h i 我用 1 2 3 4 5 6 7 8代替。
运行结果:
这里写图片描述
————————————————————————————————————
参考资料:算法导论第三版
http://blog.csdn.net/jnu_simba/article/details/8869876

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值