zoukankan      html  css  js  c++  java
  • 数据结构——最小生成树

    数据结构课上讲的最小生成树思路还要代码和我之前写过的ACM版的是一样的,这里都是两种算法普里姆(Prim)算法和克鲁兹卡尔(Kruskal)算法。

    https://www.cnblogs.com/wkfvawl/p/9140591.html

    普利姆算法

    struct
    {
        int  adjvex; ///保存邻接顶点下标的数组
        int  lowcost;///记录当前生成树到剩余顶点的最小权值
    } closedge[n];
     int sum=0;///最小生成树的权值
    int  Minimum(int closedge[], MGraph G)///求依附于生成树上顶点中所有边代价最下的边
    {
        int  j,p=1, min=999;///最大权值65535?
        for(j=0; j<G.vexnum; j++)
        {
            if (closedge[j].lowcost!=0&&closedge[j].lowcost<min)
            {
                ///不在生成树中的顶点而且权值最小
                min=closedge[j].lowcost;///更新
                p=j;
            }
        }
        sum=sum+min;///将该边的权值加入到最小生成树的总权值中
        return p; /*返回最小代价的边所依附的生成树外的顶点p*/
    }/* Minimum*/
    
    void MiniSpanTree_PRIM(MGraph G, int n,char u)
    {
        /*用Prim算法从第u个顶点出发构造网G的最小生成树T,并输出T的各条边,
           closedge [n] 记录从顶点集U到V-U的代价最小的边,n为图中顶点数*/
        int i,j,k;
        k=LocateVex(G,u); /*求顶点u在邻接矩阵存储的图中的位置*/
        for(j=0; j<G.vexnum; ++j) /* 辅助数组初始化*/
        {
            if(j!=k)
            {
                closedge[j].adjvex=u;
                closedge[j].lowcost=G.arcs[k][j].adj;
            }
        }
        closedge[k].lowcost=0; /*初始,U={u}*/
        printf("最小代价生成树的各条边为:
    ");
        for(i=1; i<G.vexnum; ++i) /*选择其余G.vexnum-1个顶点*/
        {
            k=Minimum(closedge,G); /*求出T的下个顶点,第k个顶点*/
            printf("%c-%c)
    ",closedge[k].adjvex,G.vexs[k]);///打印权值最小的边
            /* 输出生成树的边及权值*/
            closedge[k].lowcost=0;  /*第k个顶点并入U集*/
            for(j=0; j<G.vexnum; ++j)
            {
                if(closedge[j].lowcost!=0&&G.arcs[k][j].adj<closedge[j].lowcost)///
                {
                    ///如果新加入树的顶点k使得权值变小
                    /* 新顶点并入U集后重新选择最小边*/
                    closedge[j].adjvex=G.vexs[k]);///修改这条边邻接的顶点,表示这条边是从选出的顶点k指过来的
                    closedge[j].lowcost=G.arcs[k][j].adj;///更新更小的权值
                }
            }
        }
    }

    说明

    1.这个代码多一个adjvex数组,主要是为了打印最小生成树的边服务的,它用来保存邻接顶点的下标。
    2.lowcost数组记录当前生成树到其余顶点的最小权值。lowcost[i]=0表示i号顶点在生成树中了,换句话说,这个lowcost数组既有了dist数组的功能,又有了vist数组的功能。

    3.adjvex数组和lowcost数组是同步更新的。一旦有新的点加入到集合中,若找到权值最小的边,同时更新adjvex数组和lowcost。

    4.数组结构课更看重求解最小生成树的过程,因而需要去打印组成边,而ACM比赛更看重那个结果,也就最小生成树的权值,这里我又加上了sum,代表最小生成树的权值。

    克鲁斯卡尔算法

    typedef struct
    {
        int a,b;///边的两个结点
        int weight;///边的权值
    } Edge; ///边结构体
    int Find(int *parent,int x)
    {
        while(parent[x]!=0)///循环向上寻找下标为x顶点的根
        {
            x=parent[x];
        }
        return x;///循环结束时找到了根的下标
    }
    int parent[MAXVEX];///定义生成树的父节点(并查集)
    Edge edges[MAXVEX]; ///定义边集数组
    
    void MiniSpanTree_Kruskal(MGraph G)
    {
        int i,n,m;
        sort(edges);///按权值从小到大对边排序
        for (i= 0; i <G.vexnum; i++)
        {
            parent[i]=0;///初始化各个顶点单独形成一个集合
        }
        for (i=0;i<G.arcnum;i++)
        {
            n = Find(parent, edges[i].a);///n是这条边第一个顶点的根节点所在的下标
            m = Find(parent, edges[i].b);///n是这条边第二个顶点的根节点所在的下标
            if (n!=m)    ///根节点下标不同,就说不在一棵树上,不会形成环
            {
                parent[n] = m;///合并
                printf("(%d,%d) %d ", edges[i].a, edges[i].b, edges[i].weight);
            }
        }
    }

    这个就和之前的写法基本一致了,并查集加排序

  • 相关阅读:
    正向代理和反向代理
    python的reduce,map,zip,filter和sorted函数
    sed和awk的简单使用
    nginx+uWSGI+django+virtualenv+supervisor发布web服务器
    nginx负载均衡
    nginx入门与实战
    python开发之virtualenv与virtualenvwrapper讲解
    Linux下的python3,virtualenv,Mysql、nginx、redis安装配置
    Linux系统基础优化及常用命令
    vim与程序员
  • 原文地址:https://www.cnblogs.com/wkfvawl/p/10012200.html
Copyright © 2011-2022 走看看