图的最小生成树

目录

前言

一、生成树

生成树 

最小生成树

MST性质

二、Prime算法

1.原理

2.代码

三、Kruskal算法

1.原理

2.代码

总结


前言

        一直说要开始写CSDN可是不知道从哪里开始,今天不知道怎么突然很想写,就写了一下最小生成树。(本来最短路径也想要写的可是有点写不完了好像 就放到下次吧!)Kruscal算法在上次作业里好像只写了个排序,趁着写CSDN好好复习一下啦。要期末了如果有空的话我会继续写就当作复习啦。顺便说我好喜欢在这里的碎碎念 好像我和知识更熟了一点()


一、生成树

好像老师没有很提到生成树的概念,可能是觉得不很重要?

但是我这么爱问为什么的人怎么能不知道呢,嘻嘻()

生成树 

  1. 定义:①所有顶点都由边相连②无回路
  2. 特点:
    1. n个顶点,n-1条边
    2. 是极小连通子图:少一条边就非连通,多一条边就回路
    3. 生成树中任意两顶点之间路径唯一
    4. 一个图可以有多颗不同的生成树

最小生成树

各边权值最小的生成树

MST性质

这个似乎很重要 但我也没有很懂其实 贴张图在这里吧


二、Prime算法

1.原理

一张图包含了所有我想说的(绿色是下一步)

2.代码

//定义结构体
typedef struct{
    int adjvex;    //最小边的前一个结点(from)
    int lowcost;    //最小边的权值
}shortEdgeNode;

//找到已知的 不在U里的 最小边
int MinEdge(shortEdgeNode shortEdge[],int n){
    int min=INF;
    int k=-1;    //返回-1就是没有 全都是
    for(int i=0;i<n;i++){
        if(shortEdge[i].lowcost!=0 && shortEdge[i].lowcost<min){
            min=shortEdge[i].lowcost;
            k=i;
        }
    }
    return k;
}

//Prime(返回最小代价)
int FindMinWeight_Prime(const Graph &g,int start){
    int ans=0;
    shortEdgeNode shortEdge[g.vexNumber];    //储存的是每个点到U的最小权值!!!
    for(int i=0;i<g.vexNumber;i++){
        shortEdge[i].adjvex=start;    //初始化是start直达的权值
        shortEdge[i].lowcost=g.adjMatrix[start][i];
    }
    shortEdge[start].lowcost=0;    //自己到自己是0
    for(int i=0;i<g.vexNumber-1;i++){
        int k=MinEdge(shortEdge,g.vexNumber);    //这里用到函数MinEdge
        ans+=shortEdge[k].lowcost;
        shortEdge[k].lowcost=0;    //找到最小的就纳入U 这样自己到自己为0
        for(int j=0;j<g.vexNumber;j++){
            if(g.adjMatrix[k][j]<shortEdge[j].lowcost){
                shortEdge[j].lowcost=g.adjMatrix[k][j];    //如果新加入节点到j距离更小 更新lowcost值
                shortEdge[j].adjvex=k;
            }
        }
    }
    return ans;
}

三、Kruskal算法

1.原理

从边最小的开始 只要不成环 就加进去

重点是判断是否成环。这里是把每一个结点看成独立的树,每加入一条边,就是在对两棵树合并。所以需要在加入边之前判断这个边连接的两个顶点是否在同一棵树,通过parent数组一直向上查找直到找到根节点就可以啦。

2.代码

//边节点
typedef struct{
    int from,to;
    int weight;
}EdgeType;

//边从小到大排序
void sort_Kruscal(EdgeGraph &eg){
    for(int i=0;i<eg.edgeNum;i++){
        for(int j=i+1;j<eg.edgeNum;j++){
            if(eg.edge[i].weight>eg.edge[j].weight){
                EdgeType t;
                t=eg.edge[i];
                eg.edge[i]=eg.edge[j];
                eg.edge[j]=t;
            }
        }
    }
}

int parent[MAX_SIZE];

//寻找生成树的根节点
int findRoot(int v){
    int t=v;
    while(parent[t]!=-1){   //-1表示是根节点
        t=parent[t];
    }
    return t;    //!注意这里返回的是具体某个节点
}
//Kruscal(返回最小代价)
int Kruscal(EdgeGraph &eg){
    memset(parent,-1,sizeof parent);    //初始化parent数组 最开始各个顶点独立 都是根节点
    sort_Kruscal(eg);
    int ans=0;
    int num=0;
    for(int i=0;i<eg.edgeNum;i++){
        int vex1=findRoot(eg.edge[i].from);
        int vex2=findRoot(eg.edge[i].to);
        if(vex1!=vex2){     //如果根节点不同说明不能成环
            parent[vex2]=vex1;      //合并两树
            ans+=eg.edge[i].weight;
            num++;
            if(num==eg.vertexNum-1){    //结束条件是 生成树的边数=n-1
                return ans;
            }
        }
    }
return -1;    //如果遍历完成num<eg.vertexNum-1 说明不能生成
}


总结

我的第一篇CSDN耶耶耶!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值