首页后端开发ASP.NETc语言最小生成树的实现

c语言最小生成树的实现

时间2024-01-31 08:27:02发布访客分类ASP.NET浏览706
导读:收集整理的这篇文章主要介绍了c语言最小生成树的实现,觉得挺不错的,现在分享给大家,也给大家做个参考。1.最小生成树介绍什么是最小生成树?最小生成树(Minimum spanning tree,MST)是在一个给定的无向图G(V,E 中求一棵...
收集整理的这篇文章主要介绍了c语言最小生成树的实现,觉得挺不错的,现在分享给大家,也给大家做个参考。

1.最小生成树介绍

什么是最小生成树?

最小生成树(Minimum spanning tree,MST)是在一个给定的无向图G(V,E)中求一棵树T,使得这棵树拥有图G中的所有顶点,且所有边都是来自图G中的边,并且满足整棵树的边权值和最小。

2.PRim算法

和dijkstra算法很像!!请看如下Gif图,prim算法的核心思想是对图G(V,E)设置集合S,存放已被访问的顶点,然后每次从集合V-s中选择与集合S的最短距离最小的一个顶点(记为u),访问并加入集合S。之后,令顶点u为中间点,优化所有从u能到达的顶点v与集合s之间的最短距离。这样的操作执行n次,直到集合s中包含所有顶点。

不同的是,Dijkstra算法中的dist是从源点s到顶点w的最短路径;而prim算法中的dist是从集合S到顶点w的最短路径,以下是他们的伪码描述对比,关于Dijkstra算法的详细描述请参考文章

算法实现:

#includeiostream>
    #includevector>
    #define INF 100000#define MaxVertex 105tyPEdef int Vertex;
     int G[MaxVertex][MaxVertex];
    int parent[MaxVertex];
       // 并查集 int dist[MaxVertex];
     // 距离 int Nv;
        // 结点 int Ne;
        // 边 int sum;
      // 权重和 using namespace std;
     vectorVertex>
     MST;
  // 最小生成树 // 初始化图信息 void build(){
        Vertex v1,v2;
        int w;
        cin>
    >
    Nv>
    >
    Ne;
        for(int i=1;
    i=Nv;
i++){
            for(int j=1;
    j=Nv;
    j++)            G[i][j] = 0;
      // 初始化图         dist[i] = INF;
       // 初始化距离        parent[i] = -1;
  // 初始化并查集     }
        // 初始化点    for(int i=0;
    iNe;
i++){
            cin>
    >
    v1>
    >
    v2>
    >
    w;
            G[v1][v2] = w;
            G[v2][v1] = w;
    }
}
// Prim算法前的初始化 void IniPrim(Vertex s){
        dist[s] = 0;
        MST.push_back(s);
        for(Vertex i =1;
    i=Nv;
i++)        if(G[s][i]){
                dist[i] = G[s][i];
                parent[i] = s;
        }
 }
// 查找未收录中dist最小的点 Vertex FindMin(){
        int min = INF;
        Vertex xb = -1;
        for(Vertex i=1;
    i=Nv;
    i++)        if(dist[i] &
    &
 dist[i]  min){
                 min = dist[i];
                xb = i;
        }
        return xb;
}
void output(){
        cout"被收录顺序:"endl;
         for(Vertex i=1;
    i=Nv;
    i++)        coutmST[i]" ";
        cout"权重和为:"sumendl;
         cout"该生成树为:"endl;
         for(Vertex i=1;
    i=Nv;
    i++)        coutparent[i]" ";
}
void Prim(Vertex s){
        IniPrim(s);
    while(1){
            Vertex v = FindMin();
            if(v == -1)            break;
            sum += dist[v];
            dist[v] = 0;
            MST.push_back(v);
            for(Vertex w=1;
    w=Nv;
    w++)            if(G[v][w] &
    &
 dist[w])                if(G[v][w]  dist[w]){
                        dist[w] = G[v][w];
                        parent[w] = v;
                }
    }
}
int main(){
        build();
        Prim(1);
        output();
        return 0;
}
    

关于prim算法的更加详细讲解请参考视频 https://www.bilibili.COM/video/av55114968?p=99

3.kruskal算法

Kruskal算法也可以用来解决最小生成树的问题,其算法思想很容易理解,典型的边贪心,其算法思想为:

● 在初始状态时隐去图中所有的边,这样图中每个顶点都是一个单独的连通块,一共有n个连通块

● 对所有边按边权从小到大进行排序

● 按边权从小到大测试所有边,如果当前测试边所连接的两个顶点不在同一个连通块中,则把这条测试边加入当前最小生成树中,否则,将边舍弃。

● 重复执行上一步骤,直到最小生成树中的边数等于总顶点数减一 或者测试完所有边时结束;如果结束时,最小生成树的边数小于总顶点数减一,说明该图不连通。

请看下面的Gif图!

算法实现:

#includeiostream>
    #includestring>
    #includevector>
    #includequeue>
    #define INF 100000#define MaxVertex 105typedef int Vertex;
     int G[MaxVertex][MaxVertex];
    int parent[MaxVertex];
       // 并查集最小生成树 int Nv;
        // 结点 int Ne;
        // 边 int sum;
      // 权重和 using namespace std;
 struct Node{
        Vertex v1;
        Vertex v2;
        int weight;
     // 权重     // 重载运算符成最大堆     bool operator  (const Node &
a) const    {
            return weight>
    a.weight;
    }
}
    ;
    vectorNode>
     MST;
      // 最小生成树 priorITy_queueNode>
     q;
   // 最小堆 // 初始化图信息 void build(){
        Vertex v1,v2;
        int w;
        cin>
    >
    Nv>
    >
    Ne;
        for(int i=1;
    i=Nv;
i++){
            for(int j=1;
    j=Nv;
    j++)            G[i][j] = 0;
      // 初始化图        parent[i] = -1;
    }
        // 初始化点    for(int i=0;
    iNe;
i++){
            cin>
    >
    v1>
    >
    v2>
    >
    w;
            struct Node tmpE;
            tmpE.v1 = v1;
            tmpE.v2 = v2;
            tmpE.weight = w;
            q.push(tmpE);
     }
}
//  路径压缩查找 int Find(int x){
        if(parent[x]  0)        return x;
        else        return parent[x] = Find(parent[x]);
}
 //  按秩归并 void Union(int x1,int x2){
    if(parent[x1]  parent[x2]){
            parent[x1] += parent[x2];
            parent[x2] = x1;
    }
else{
            parent[x2] += parent[x1];
            parent[x1] = x2;
    }
}
 void Kruskal(){
        // 最小生成树的边不到 Nv-1 条且还有边     while(MST.size()!= Nv-1 &
    &
 !q.empty()){
            Node E = q.top();
      // 从最小堆取出一条权重最小的边        q.pop();
 // 出队这条边         if(Find(E.v1) != Find(E.v2)){
      // 检测两条边是否在同一集合             sum += E.weight;
                 Union(E.v1,E.v2);
         // 并起来             MST.push_back(E);
        }
    }
    }
 void output(){
        cout"被收录顺序:"endl;
         for(Vertex i=0;
    iNv;
    i++)        coutMST[i].weight" ";
        cout"权重和为:"sumendl;
         for(Vertex i=1;
    i=Nv;
    i++)        coutparent[i]" ";
        coutendl;
}
int main(){
        build();
        Kruskal();
        output();
        return 0;
}
    

关于kruskal算法更详细的讲解请参考视频 https://www.bilibili.com/video/av55114968?p=100

推荐课程:c语言教程

以上就是c语言最小生成树的实现的详细内容,更多请关注其它相关文章!

声明:本文内容由网友自发贡献,本站不承担相应法律责任。对本内容有异议或投诉,请联系2913721942#qq.com核实处理,我们将尽快回复您,谢谢合作!

c语言

若转载请注明出处: c语言最小生成树的实现
本文地址: https://pptw.com/jishu/593719.html
聊聊Angular中与视图有关的一些定义 Javascript迭代器的用法是什么

游客 回复需填写必要信息