首页 > 编程语言 >构建最小生成树(Prim算法和Kruskal算法)

构建最小生成树(Prim算法和Kruskal算法)

时间:2024-11-16 22:15:48浏览次数:3  
标签:vexnum Prim map int Kruskal 算法 Edge 顶点 include

其中克鲁斯卡尔算法中判断是否发生自环也可采用DFS和BFS判断,这里采用是并查集

#include <iostream>
#include<algorithm>
#include<vector>
using namespace std;
#define INF 100000000;
class Edge
{
 public:
    int x1,x2;//边的两个顶点
    int w;//权
    Edge(int X1,int X2, int W):x1(X1),x2(X2),w(W){}
    
};
bool compare(Edge e1,Edge e2)
{
    return e1.w<e2.w;
}
int find_min(int *a,int n)
{
    int min=INF;
    int minloc=-1;
    for(int i=0;i<n;i++)
    {
        if(a[i]!=0&&min>a[i])
        {
            min=a[i];
            minloc=i;
        }
    }
    return minloc;
}
void print_map(int *a,int n)
{
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<n;j++)
        {
            cout<<*(a+i*n+j)<<' ';
        }
        cout<<endl;
    }
    cout<<endl;
}
int find(int *a,int x)   //并查集,查找当前节点的根节点的下标
{
    while(a[x]!=-1)
        x=a[x];
    return x;
}
class Graph
{
 public:
    int vexnum;         //顶点个数
    int** arc;          //邻接矩阵
    Graph(int num)      //初始化,分配内存
    {
        vexnum=num;
        arc=new int* [num];
        for(int i=0;i<num;i++) arc[i]=new int[num];
    }
    void input()        //输入
    {
        for(int i=0;i<vexnum;i++)
            for(int j=0;j<vexnum;j++)
                cin>>arc[i][j];
    }
    void Prim()           //prim算法
    {
        int minDistant[vexnum];//生成树内的顶点到各点的最小距离:若为无穷(INF),则为不可到达;若为0,则为该顶点在生成树内
        int parent[vexnum];//记录mindistant中的最小距离是由哪个生成树的顶点到该点的距离,若mindistant为INF,则为-1
        int current_map[vexnum][vexnum];//当前生成树的邻接矩阵
        for(int i=0;i<vexnum;i++)//对上述三个数组进行初始化,mindistant初始为INF,parent为-1,邻接矩阵为0;
        {
            minDistant[i]=INF;
            parent[i]=-1;
            for(int j=0;j<vexnum;j++) current_map[i][j]=0;
        }
        int point=0;
        minDistant[0]=0;//从0开始
        while(true)
        {
            print_map((int*)current_map,vexnum);//输出当前邻接矩阵  
            for(int i=0;i<vexnum;i++)//更新,看新加入的点到其他点是否存在更短的距离
            {
                if(arc[point][i]!=0&&arc[point][i]<minDistant[i])
                {
                    minDistant[i]=arc[point][i];
                    parent[i]=point;
                }
            }
            int min_point=find_min(minDistant,vexnum);//找出在mindistant找距离最短的一个点,如果没找到则返回-1。
            if(min_point==-1)//-1说明所有顶点已经全在生成树内
                break;
            current_map[min_point][parent[min_point]]=current_map[parent[min_point]][min_point]=arc[parent[min_point]][min_point];
            //将新节点和与距离新节点最短距离的节点(parent v)连接
            point=min_point;//记录该最短节点,以此循环将该节点假如生成树内
            minDistant[point]=0; //加点,0代表在生成树内 
        }
    } 
    void Kruskal()
    {
        vector<Edge> edge;   //将所有的边的信息存入数组
        bool visited[vexnum];//顶点访问信息
        int parent[vexnum];//每个节点对应的父节点,-1为根节点
        int current_map[vexnum][vexnum];//当前邻接矩阵
        for(int i=0;i<vexnum;i++)//上述数组初始化
        {
            visited[i]=false;
            parent[i]=-1;
            for(int j=0;j<vexnum;j++) current_map[i][j]=0;
        }
        for(int i=0;i<vexnum;i++)//通过邻接矩阵传入边的信息
        {
            for(int j=i+1;j<vexnum;j++) 
            {
                if(arc[i][j]!=0)
                    edge.push_back(Edge(i,j,arc[i][j]));
            }
        }
        sort(edge.begin(),edge.end(),compare);//升序排序
        for(int i=0;i<edge.size();i++)//遍历每个边的信息
        {  
     
            int x1=edge[i].x1,x2=edge[i].x2;
            if(find(parent,x1)==find(parent,x2)) continue;//若这两个顶点的根节点来自同一个根节点,那么他们不能相连,否则会发生自环;
            print_map((int*)current_map,vexnum);//打印当前邻接矩阵,二维数组必须转化成一维数组才能传入
            if(visited[x1]==false&&visited[x2]==false) //如果两个节点都未访问过,随便令一个为根,另一个为其子节点
                parent[x2]=x1;
            else if(visited[x1]==false) //若其中一个访问过,另一个没有,那么让没有访问过的节点为访问过的节点的子节点
                parent[x1]=x2;
            else if(visited[x2]==false)
                parent[x2]=x1;
            else       //若两个都被访问过,且不同根(不是同一个连通分量),那么将这两个集合合并,即让任意一个的根节点等于另一个的子节点
            {
                int root1=find(parent,x1);
                int root2=find(parent,x2);
                parent[root2]=root1;
            }
            visited[x1]=visited[x2]=true;
            current_map[x1][x2]=current_map[x2][x1]=arc[x1][x2];// 更新至当前邻接矩阵
        }
        print_map((int*)current_map,vexnum);
    }
};

int main() {
   int n; 
   cin>>n;
   Graph graph(n);
   graph.input();
   cout<<"Prim:"<<endl;
   graph.Prim();
   cout<<"Kruskal:"<<endl;
   graph.Kruskal();

}
// 64 位输出请用 printf("%lld")

标签:vexnum,Prim,map,int,Kruskal,算法,Edge,顶点,include
From: https://blog.csdn.net/2303_79737961/article/details/143783601

相关文章

  • 代码随想录算法训练营第四十七天|Day47 单调栈
    739.每日温度https://programmercarl.com/0739.%E6%AF%8F%E6%97%A5%E6%B8%A9%E5%BA%A6.html思路int*dailyTemperatures(int*temperatures,inttemperaturesSize,int*returnSize){int*answer=(int*)malloc(temperaturesSize*sizeof(int));int*sta......
  • 代码随想录算法训练营第四十八天|Day48 单调栈
    42.接雨水https://programmercarl.com/0042.%E6%8E%A5%E9%9B%A8%E6%B0%B4.html思路inttrap(int*height,intheightSize){intans=0;intleft=0,right=heightSize-1;intleftMax=0,rightMax=0;......
  • 算法沉淀一:双指针
    目录前言:双指针介绍对撞指针快慢指针题目练习1.移动零2.复写零3.快乐数4.盛水最多的容器5.有效三角形的个数6.和为s的两个数7.三数之和8.四数之和前言:此章节介绍一些算法,主要从leetcode上的题来讲解,讲解内容为做题思路,附加代码。欢迎与我大家一起学习共同进......
  • LL(1)分析算法
    LL(1)分析算法从左(L)向右读入程序,最左(L)推导,采用一个(1)前看符号.分析高效(线性时间)错误定位和诊断信息准确有很多开源或商业的生成工具ANTLR算法基本思想表驱动的分析算法graphLRx1["词法分析器"]--"记号\n\n"-->x2["语法分析器"]---->x3["......
  • 【模板】最小生成树-kruskal
    intfather[5010],n,m;intfind(intx)//找根函数,记得进行路径压缩{if(father[x]==x)returnx;elsereturnfather[x]=find(father[x]);}intsame(intx,inty)//简化代码{if(find(x)==find(y))return1;elsereturn0;}structedge{......
  • 【转载】遗传算法—HyperNEAT Explained——Advancing Neuroevolution
    原文地址:https://hunterheidenreich.com/posts/next-gen-neuroevolution-hyperneat/ExpandingNeuroEvolutionLastweek,IwroteanarticleaboutNEAT(NeuroEvolutionofAugmentingTopologies)andwediscussedalotofthecoolthingsthatsurroundedthealgori......
  • Python实现Graham Scan算法并进行凸包计算
    目录使用GrahamScan算法进行凸包计算第一部分:GrahamScan算法概述1.1什么是GrahamScan算法?1.2算法的应用场景1.3算法的优点和局限第二部分:算法的数学基础与步骤2.1凸包的定义与性质2.2算法的关键步骤2.3极角计算公式2.4算法流程图第三部分......
  • Jarvis March算法详解及Python实现(附设计模式案例)
    目录JarvisMarch算法详解及Python实现(附设计模式案例)第一部分:JarvisMarch算法概述与原理1.1什么是JarvisMarch算法?1.2算法原理1.3算法流程1.4时间复杂度第二部分:JarvisMarch算法的Python实现(面向对象设计)2.1面向对象设计2.2代码实现2.3代......
  • 【转载】遗传算法—Exploring NEAT-Neuroevolution of Augmenting Topologies
    原文地址:https://hunterheidenreich.com/posts/neuroevolution-of-augmenting-topologies/AWorldofNeuroEvolutionRecently,I’vebeendoingalotofreadingaboutsomethingcalledneuroevolution.Atahigh-level,theideaisverysimple.Insteadofrelyingo......
  • 哈夫曼树的构造过程及算法实现
    一、哈夫曼树的构造过程(1)根据给定的n个权值{w1,w2,...,wn},构造n棵只有根节点的二叉树,这n棵二叉树构成森林F。(2)在森林F中选取两棵根节点的权值最小的树作为左右子树构造一棵新的二叉树,且置新的二叉树的根节点的权值为其左右子树上根节点的权值之和。(3)在森林F中删除这两棵树,同......