第七章 图(三)图算法的应用

@第七章 图(三)
图算法的应用
最小生成树 :普里姆算法「Prim」、克鲁斯卡尔算法「Kruskal」

一、普里姆算法实现最小生成树

---------------------------------------------------------------------------------------------------------------------
第七章 图(三)图算法的应用_第1张图片 第七章 图(三)图算法的应用_第2张图片
图1、图2
第七章 图(三)图算法的应用_第3张图片
图3
首先主程序构造了如图2所示的无向网,然后调用MiniSpanTree_PRIM(),由顶点V1开始,求该网的最小生成树。最小生成树顶点集最初只有V1,其中用到了辅助数组 closedge[]。closedge[i].lowcost 是最小生成树顶点集中的顶点到 i 点的最小权值。若i点属于最小生成树,则closedge[i].lowcost=0。closedge[i].adjvex 是最小生成树顶点集U中到i点为最小权值的那个顶点的序号。图 3(a)显示了 closedge[]的初态。这时U中只有 V1,所以closedge[i].adjvex都是 V1,closedge[i].lowcost是V1 到顶点i的权值。closedge[0].lowcost=0,说明 V1 已并入U了。在closedge[].lowcost 中找最小正数,closedge[2].lowcost=1,是最小正数。令 k=2,将 V3 并入U,令closedge[2].lowcost=0),输出边(V1—V3)。因为 V3到V2、V5和V6的权值小于V1到它们的权值,故将它们的closedge[].lowcost替换为V3到它们的权值;将它们的 closedge[].adjvex 替换为V3,如图3(b)所示。重复这个过程,依次如图3(c)、(d)和(e)所示。最后,closedge[]包含了最小生成树中每一条边的信息。
---------------------------------------------------------------------------------------------------------------------
//邻接矩阵实现普里姆算法
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define MaxVertexNum 100
typedef int EdgeType;
typedef char VertexType[10];
typedef struct
{
    VertexType vertex[MaxVertexNum];            //顶点表
    EdgeType edges[MaxVertexNum][MaxVertexNum]; //邻接矩阵,即边表
    int n,e;        //顶点数和边数
}MGraph;
typedef struct
{
    VertexType adjvex;
    int lowcost;
}miniside[MaxVertexNum];
int LocateVex(MGraph G,VertexType u)
{
    int i;
    for(i=0;i>G.n>>G.e;
    cout<<"请输入顶点信息(输入格式为:顶点号):"<>G.vertex[i];
    for(i=0;i>vi>>vj>>w;
        i=LocateVex(G,vi);
        j=LocateVex(G,vj);
        G.edges[i][j]=w;
        G.edges[j][i]=w;
    }   
    
}//CreateMGraphAN
int minimum(miniside S,MGraph G)
{ //求S的最小值,并返回其在S中的序号
    int i=0,j,k,min;
    while(!S[i].lowcost) //找第一个值不为0的S[i].lowcost的序号
        i++;
    min=S[i].lowcost; //min标记第一个不为0的值
    k=i;//k表示该值的序号
    for(j=i+1;j0 && S[j].lowcost < min)//找到更小的新的正值
            {
                min=S[j].lowcost;//min标记此正值
                k=j;//k标记此正值的序号
            }
        return k; //返回当前最小正值在S中的序号
}
void Prim(MGraph G,VertexType u)
{ //用prim算法从顶点u出发构造网G的最小生成树T,输出T的各边
    int i,j,k;
    miniside S;
    k=LocateVex(G,u); //顶点u的序号
    for(j=0;j"<

输出结果

请输入顶点数和边数(输入格式为:顶点数,边数):
5 8
请输入顶点信息(输入格式为:顶点号):
v1
v2
v3
v4
v5
请输入8条边对应的两个顶点的序号及权值(输入格式为:顶点1,顶点2,权值)顶点1,顶点2,权值:
v1 v2 4
顶点1,顶点2,权值:
v1 v3 1
顶点1,顶点2,权值:
v1 v4 5
顶点1,顶点2,权值:
v2 v3 4
顶点1,顶点2,权值:
v2 v5 2
顶点1,顶点2,权值:
v3 v4 4
顶点1,顶点2,权值:
v3 v5 3
顶点1,顶点2,权值:
v4 v5 5
输出图的邻接矩阵:
   0   4   1   5   0
   4   0   4   0   2
   1   4   0   4   3
   5   0   4   0   5
   0   2   3   5   0
最小代价生成树的各条边为:
v1->v3
v3->v5
v5->v2
v3->v4

二、克鲁斯卡尔算法

#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define MaxVertexNum 100

typedef int EdgeType;
typedef char VertexType[10];

typedef struct
{
    VertexType vertex[MaxVertexNum];            //顶点表
    EdgeType edges[MaxVertexNum][MaxVertexNum]; //邻接矩阵,即边表
    int vexnum,edgenum;        //顶点数和边数
}MGraph;

struct side
{
    int a,b;//边的两顶点序号
    int weight; //边的权值
};

int LocateVex(MGraph G,VertexType u)
{
    int i;
    for(i=0;i>G.vexnum>>G.edgenum;
    cout<<"请输入顶点信息(输入格式为:顶点号):"<>G.vertex[i];
    for(i=0;i>vi>>vj>>w;
        i=LocateVex(G,vi);
        j=LocateVex(G,vj);
        G.edges[i][j]=w;
        G.edges[j][i]=w;
    }   
}//CreateMGraphAN

void Kruskal(MGraph G)
{
    int set[MaxVertexNum],senumber=0,sb,i,j,k;
    side se[MaxVertexNum*(MaxVertexNum-1)/2];//存储边信息的一维数组
    for(i=0;i0 && G.edges[i][j]=0)
                if(se[k].weight>G.edges[i][j])
                {
                    se[k+1]=se[k];
                    k--;
                }         
            else
                break;
            se[k+1].a=i;
            se[k+1].b=j;
            se[k+1].weight=G.edges[i][j];
            senumber++;
         }
    cout<<"i  se[i].a  se[i].b  se[i].weight"<
---------------------------------------------------------------------------------------------------------------------
第七章 图(三)图算法的应用_第4张图片 第七章 图(三)图算法的应用_第5张图片
图4、图5
首先,主程序构造了图4所示的无向网。然后,调用 kruskal(),求该网的最小生成树。其中用到了辅助数组 set[]。set[i]表示第 i 个顶点所在的集合。设初态 set[i]=i,6个顶点分属于6个集合,如图5(a)所示。在邻接矩阵的上三角中找权值最小的边(因为是无向网),边(V1—V3)的权值最小,将V1和V3并到1个集合中。方法是将V3的集合set[2]赋值为set[0](V1的集合),同时将该边删除(令其上在三角的值为无穷)并输出该 边,如图5(b)所示。用此方法依次将V4和V6、V2和V5 分别并到1个集合中,如图5(c)、图5(d)所示。这时,邻接矩阵上三角中权值最小的边是(V3—V6),这 两顶点分属于两个集合0和3。将集合3合并到集合0中。方法是把集合3中的V4、V6都并到集合0中,如图5(e)所示。这时在邻接矩阵的上三角中首先找到的权值最小边是(V1—V4),但它们属于同一个集合(set[0]=set[3]=0),删除该边,继续查找。找到(V2—V3)是权值最小的边,且它们分属于不同的集合。把V3所在集合中的顶点都并到V2所在集合中,使所有顶点都在集合1中,如图5(f)所示,最后构成了最小生成树。程序运行结果和普里姆算法的一样。
---------------------------------------------------------------------------------------------------------------------

你可能感兴趣的:(数据结构)