最小生成树(算法篇)

news2024/7/30 4:16:46

算法之最小生成树

最小生成树

概念

  • 最小生成树是一颗连接图G所有顶点的边构成的一颗权最小的树最小生成树一般是在无向图中寻找。
  • 最小生成树共有N-1条边(N为顶点数)

算法

Prim算法

概念

  • Prim(普里姆)算法是生成最小生成树的一种算法,该算法基本上和求最短路径的Dijkstra算法一样
  • 具体操作:选取一个顶点作为树的根节点v1,然后从这个顶点发散,找到其邻接顶点(加入队列中),然后选取根节点到邻接顶点中权最小的路径(也就是连接该路径的另一个顶点)进行添加到树中(也将连接的顶点除去v1的顶点的邻接顶点加入队列中),然后初步形成一个图为u,然后再按顺序的查找图u与队列中的顶点的最小路径并加入树中,重复操作。
  • 最小生成树信息打印,打印树中边的顶点对组

实现代码:

使用优先队列

void Prim(int v){
        an[v].dist=0;
        //使用优先队列,定义参数<数据类型,容器类型,比较方法>
        priority_queue<pair<int,int>,vector<pair<int,int>>,greater<pair<int,int>>>q;
        //pair<int,int>对组的第一个为权,第二个为顶点。
        q.push(make_pair(0,v));
        while (!q.empty()){
            int w=q.top().second;
            q.pop();
            listnode* p=an[w].next;
            if(an[w].flag) continue;
            while (p!= nullptr){
                //选取最小权的边而不是顶点到顶点的最短距离
                if(p->weight<an[p->data].dist&&!an[p->data].flag){
                    an[p->data].dist=p->weight;
                    an[p->data].path=w;
                    q.push(make_pair(p->weight,p->data));
                }
                p=p->next;
            }
            an[w].flag= true;
        }
        int w=0;     //记录最小生成树的总权
        for(int i=1;i<=vnum;i++){
            if(an[i].path!=0){
                if(i>an[i].path)
                    cout<<"("<<an[i].path<<","<<i<<")"<<" 权:"<<an[i].dist<<endl;
                else
                    cout<<"("<<i<<","<<an[i].path<<")"<<" 权:"<<an[i].dist<<endl;
                w+=an[i].dist;
            }
        }
        cout<<"总权:"<<w;
        cout<<endl;
    }

使用vector容器模拟优先队列

struct edge{
    int v;    //顶点
    int weight;   //权
};
static bool cmp(const edge &a,const edge &b){
        return b.weight<a.weight;
    }
    void Prim(int v){
        an[v].dist=0;
        vector<edge>q;
        q.push_back({v,0});
        while (!q.empty()){
            sort(q.begin(),q.end(),cmp);
            int w=q.back().v;
            q.pop_back();
            listnode* p=an[w].next;
            if(an[w].flag) continue;
            while (p!= nullptr){
                //选取最小权的边而不是顶点到顶点的最短距离
                if(p->weight<an[p->data].dist&&!an[p->data].flag){
                    an[p->data].dist=p->weight;
                    an[p->data].path=w;
                    q.push_back({p->data,p->weight});
                }
                p=p->next;
            }
            an[w].flag= true;
        }
        int w=0;     //记录最小生成树的总权
        for(int i=1;i<=vnum;i++){
            if(an[i].path!=0){
                if(i>an[i].path)
                    cout<<"("<<an[i].path<<","<<i<<")"<<" 权:"<<an[i].dist<<endl;
                else
                    cout<<"("<<i<<","<<an[i].path<<")"<<" 权:"<<an[i].dist<<endl;
                w+=an[i].dist;
            }
        }
        cout<<"总权:"<<w;
        cout<<endl;
    }

Kruskal算法

概念

  • Kruskal(克鲁斯卡尔)算法是连续地按照最小的权选择边,并且当所选的边不产生圈时就把它作为最小生成树中的边。
  • 该算法是在处理一个森林–树的集合。开始的时候,存在|V|棵单节点树,而添加一边则将两棵树合并成一颗树。当算法终止时,就只有一棵树,就是最小生成树。
并查集
  • 并:合并,查:查询连通关系,集:形成集合,用于处理连通性问题

  • 并查集:集合中的元素组织成树的形式

  1. 查找两个元素是否属于同一集合:所在树的根结点是否相同

  2. 合并两个集合——将一个集合的根结点作为另一个集合根结点的孩子

具体操作

  • 该算法是根据选取边来进行生成最小生成树,那么我们就将图的信息用一个边集结构表示,我们需要进行一个循环,循环条件就是当最小生成树的边达到N-1条时就退出(N为元素个数),每次循环我们都需要选取最小权重的边,并且判断在树中加入这条边会不会形成圈,如果形成圈就不进行加入,直到树的边条数达到N-1就形成了最小生成树。
  • 该算法的关键是判断在树中加入边会不会形成圈–也就是判断两个顶点是否位于两个连通分量,这就需要并查集的操作:在图中我们将每个顶点都当作一个集合,我们插入边的时候,直接判断这两个顶点是否处于一个集合中,如何是一个集合就不进行加入,如果不是一个集合,就需要将两个集合进行合并,那么这就需要一个存储每个节点的根(父亲)节点的数组parent。我们将parent每个连通分量(集合)进行初始化为-1,表示没有父亲。

实现代码:

struct edge{
    int u,v,w;  //u,v为顶点的,w为权重,u为起始点,v为终点
};

static bool cmp(const edge &a,const edge &b){
        return a.w<b.w;
    }
    int findroot(int v,int parent[]){
        int t=v;
        while (parent[t]>-1){    //查找该集合的根节点。
            t=parent[t];
        }
        return t;
    }
    void Kruskal(int v){
        vector<edge>q;
        //存储每个连通变量的父亲节点的数组
        int parent[vnum+1];
        int w=0;     //记录最小生成树的总权
        memset(parent,-1, sizeof(int)*(vnum+1));
        //生成边集数组。
        for(int i=1;i<=vnum;i++) {
            listnode *p = an[i].next;
            while (p != nullptr) {
                if(i<p->data)
                    q.push_back({i, p->data, p->weight});
                p = p->next;
            }
        }
        //进行排序将最小权边放入第一位。
        sort(q.begin(),q.end(), cmp);
        for(int i=0,num=0;num<vnum-1;i++){
            int v1=findroot(q[i].u,parent);
            int v2= findroot(q[i].v,parent);
            //判断祖先节点是否相等--判断是否在一个集合.
            if(v1!=v2){
                cout<<"("<<q[i].u<<","<<q[i].v<<")"<<" 权:"<<q[i].w<<endl;
                w+=q[i].w;
                parent[v2]=v1;    //合并集合。
                num++;
            }
        }
        cout<<"总权:"<<w;
        cout<<endl;
    }

尾言

完整版笔记也就是数据结构与算法专栏完整版可到我的博客进行查看,或者在github库中自取(包含源代码)

  • 博客1: codebooks.xyz
  • 博客2:moonfordream.github.io
  • github项目地址:Data-Structure-and-Algorithms

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1917081.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringBoot项目架构实战之“网关zuul搭建“

第三章 网关zuul搭建 前言&#xff1a; 1、主要功能 zuul主要提供动态路由&#xff08;内置ribbon实现&#xff09;和过滤&#xff08;可以做统一鉴权过滤器、灰度发布过滤器、黑白名单IP过滤器、服务限流过滤器&#xff08;可以配合Sentinel实现&#xff09;&#xff09;功能…

【IT领域新生必看】解锁 `final` 关键字的秘密:Java 编程中的终极武器

文章目录 引言什么是 final 关键字&#xff1f;一、 final 变量final 局部变量final 实例变量final 静态变量 二、 final 方法三、 final 类四、 final 关键字的实际应用1. 定义常量2. 防止方法被重写3. 创建不可变类4. 优化性能 五、 final 的一些常见误区1. final 变量不能在…

力扣2356.二维差分模板——子矩阵元素加1

力扣2356.二维差分模板——子矩阵元素加1 模板题 最后将n2*n2的矩阵删去周围一圈变成n*n矩阵的操作 class Solution {public:vector<vector<int>> rangeAddQueries(int n, vector<vector<int>>& queries) {vector<vector<int>> res…

ONLYOFFICE 8.1版本版本桌面编辑器测评

ONLYOFFICE官网链接&#xff1a;ONLYOFFICE - 企业在线办公应用软件 | ONLYOFFICE ONLYOFFICE在线办公套件&#xff1a;在线办公套件 | ONLYOFFICE ONLYOFFICE在线PDF编辑器、阅读器和转换器&#xff1a;在线PDF查看器和转换器 | ONLYOFFICE ONLYOFFICE 8.1版本桌面编辑器是…

【OC】巧用UIStackView简化布局

UIStackView的运用 文章目录 UIStackView的运用引入UIStackView的作用UIStackView的属性compression resistance 和 huggingaxisalignmentDistributionspacing UIStackView的方法UIStackView的示例 引入 在仿写ZARA的过程之中&#xff0c;我看到软件之中是有大量的按钮排列在一…

蓝卓创始人褚健:未来工厂需要一个“工业安卓”

作为国内自动控制的科学家&#xff0c;过去近三十年的时间&#xff0c;褚健教授一直服务于化工行业、炼油石化等流程工业领域。褚健表示&#xff0c;因为涉及到安全生产和环保要求&#xff0c;流程工业企业的自动化水平高一些&#xff0c;但总体来看&#xff0c;目前中国大部分…

【网络安全】SSRF 之 Azure Digital Twins Explorer

未经许可&#xff0c;不得转载。 文章目录 正文 正文 Azure Digital Twins 是一个微软下的平台服务&#xff0c;允许开发者创建和运行数字孪生模型&#xff0c;这些模型能够反映物理世界中的实体及其关系&#xff0c;通过这些模型可以进行监控、分析和预测等操作。 1、进入主…

昇思25天学习打卡营第17天|基于 MindSpore 实现 BERT 对话情绪识别

基于 MindSpore 实现 BERT 对话情绪识别 BERT介绍 BERT&#xff08;Bidirectional Encoder Representations from Transformers&#xff09;是一种基于Transformer架构的预训练语言模型&#xff0c;由谷歌在2018年提出。从以下6个方面来介绍BERT&#xff1a; 1. 预训练和微调&…

解决keil调试遇到的hardlfault问题

在程序开发过程中遇到的程序死机问题 导致死机的原因&#xff1a;内存溢出&#xff0c;堆栈溢出&#xff0c;数组越界&#xff0c;中断错误。。。。。。 出现这个问题&#xff0c;首先查看线程的调度关系 看最后是在哪个位置死机&#xff0c;如果rt_current_thread在main_thre…

[AI 大模型] 阿里巴巴 通义千问

文章目录 [AI 大模型] 阿里巴巴 通义千问简介模型架构发展新技术和优势示例 [AI 大模型] 阿里巴巴 通义千问 简介 阿里巴巴的 通义千问 是由阿里云开发的一款大型语言模型&#xff0c;旨在为用户提供高效、智能的自然语言处理服务。 通义千问能够处理多种语言输入&#xff0c…

麒麟服务器操作系统2303SP3安装tigervnc

原文链接&#xff1a;麒麟服务器操作系统2303SP3安装tigervnc Hello&#xff0c;大家好啊&#xff01;今天给大家带来一篇关于在麒麟服务器操作系统2303SP3上安装TigerVNC的文章。TigerVNC是一款高性能的远程桌面查看器&#xff0c;它支持多种操作系统&#xff0c;允许用户在远…

Oracle序列迁移重建

原因&#xff1a;oracle数据导入后序列不一致 解决办法&#xff1a;从原库中导出一份最新的序列号&#xff0c;在目标库中导入 1.删除目标库该用户下的所有索引 select DROP SEQUENCE ||sequence_name || ; from dba_sequences where sequence_owner xxxxx;2.查询出所有序列…

DepthAnything(2): 基于ONNXRuntime在ARM(aarch64)平台部署DepthAnything

DepthAnything(1): 先跑一跑Depth Anything_depth anything离线怎么跑-CSDN博客 目录 1. 写在前面 2. 安装推理组件 3. 生成ONNX 4. 准备ONNXRuntime库 5. API介绍 6. 例程 1. 写在前面 DepthAnything是一种能在任何情况下处理任何图像的简单却又强大的深度估计模型。 …

汽车预约维修小程序的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;技师管理&#xff0c;技师信息管理&#xff0c;用户预约管理&#xff0c;取消预约管理&#xff0c;订单信息管理&#xff0c;系统管理 微信端账号功能包括&#xff1a;系统首页&#xff0c;技师信息&a…

揭秘焦虑症的“隐形杀手“:这些并发症可能悄悄来袭!

揭秘焦虑症的"隐形杀手"&#xff1a;这些并发症可能悄悄来袭&#xff01;在快节奏的现代生活中&#xff0c;焦虑症已经成为越来越多人面临的心理健康挑战。然而&#xff0c;除了广为人知的焦虑、紧张、失眠等症状外&#xff0c;焦虑症还可能引发一系列看似与焦虑无关…

每天五分钟计算机视觉:目标检测算法之R-CNN

本文重点 在计算机视觉领域,目标检测一直是一个核心问题,旨在识别图像中的物体并定位其位置。随着深度学习技术的发展,基于卷积神经网络(CNN)的目标检测算法取得了显著的进步。其中,R-CNN(Regions with CNN features)是一种开创性的目标检测框架,为后续的研究提供了重…

【高中数学/指数、对数】已知9^m=10,a=10^m-11,b=8^m-9,则ab两数和0的大小关系是?(2022年全国统考高考真题)

【问题】 已知9^m10,a10^m-11,b8^m-9,则&#xff08;&#xff09; A.a>0>b B.a>b>0 C.b>a>0 D.b>0>a 【解答】 首先注意到10^log10_11-110,8^log8_9-90&#xff0c; 问题就转化为log8_9,log9_10,log10_11谁大谁小的问题&#xff0c; 再进一步…

maven高级1——一个项目拆成多个

把原来一个项目&#xff0c;拆成多个项目。 &#xff01;&#xff01;他们之间&#xff0c;靠接口通信。 以ssm整合好的项目为例&#xff1a; 如何看拆的ok不ok 只要compile通过就ok。 拆分pojo 先新建一个项目模块&#xff0c;再把内容复制进去。 拆分dao 1.和上面一样…

可控学习综述:信息检索中的方法、应用和挑战

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…