【高阶数据结构】图的应用--最小生成树

一、最小生成树

连通图中的每一棵生成树,都是原图的一个极大无环子图,即:从其中删去任何一条边,生成树就不在连通;反之,在其中引入任何一条新边,都会形成一条回路。

若连通图由n个顶点组成,则其生成树必含n个顶点和n-1条边。因此构造最小生成树的准则有三条:

1.只能使用图中的边来构造最小生成树

2.只能使用恰好n-1条边来连接图中的n个顶点

3.选用的n-1条边不能构成回路

构造最小生成树的方法:Kruskal算法和Prim算法。这两个算法都采用了逐步求解的贪心策略。

贪心算法:是指在问题求解时,总是做出当前看起来最好的选择。也就是说贪心算法做出的不是整体最优的的选择,而是某种意义上的局部最优解。贪心算法不是对所有的问题都能得到整体最优解。

二、Kruskal算法

任给一个有n个顶点的连通网络N={V,E},首先构造一个由这n个顶点组成、不含任何边的图G={V,NULL},其中每个顶点自成一个连通分量,其次不断从E中取出权值最小的一条边(若有多条任取其一),若该边的两个顶点来自不同的连通分量,则将此边加入到G中。如此重复,直到所有顶点在同一个连通分量上为止。

核心:每次迭代时,选出一条具有最小权值,且两端点不在同一连通分量上的边,加入生成树。

在这里插入图片描述

在图23-1上执行Kruskal算法的过程。加了阴影的边属于不断增长的森林A。该算法按照边的权重大小依次进行考虑。箭头指向的边是算法每一步所考察的边。如果该条边将两棵不同的树连接起来,它就被加入到森林里,从而完成对两棵树的合并

我们对使用领接矩阵实现的图来查找最小生成树

代码实现:

// 临接矩阵
namespace Matrix
{template <class V, class W, W MAX_W = INT_MAX, bool Direction = false>class Graph{typedef Graph<V, W, MAX_W, Direction> Self;private:std::vector<V> _vertexs;             // 顶点集合std::map<V, size_t> _vIndexMap;      // 顶点的下标映射关系std::vector<std::vector<W>> _matrix; // 存储边集合的矩阵struct Edge{size_t _srci;size_t _dsti;W _w;Edge(size_t srci, size_t dsti, const W &w): _srci(srci), _dsti(dsti), _w(w){}bool operator>(const Edge &e) const{return _w > e._w;}};W Kruskal(Self &minTree){size_t n = _vertexs.size();minTree._vertexs = _vertexs;minTree._vIndexMap = _vIndexMap;minTree._matrix.resize(n);for (int i = 0; i < n; i++){minTree._matrix[i].resize(n, MAX_W);}std::priority_queue<Edge, std::vector<Edge>, std::greater<Edge>> minqueue;for (size_t i = 0; i < n; i++){for (size_t j = 0; j < n; j++){if (i < j && _matrix[i][j] != MAX_W){minqueue.push({i, j, _matrix[i][j]});}}}// 选出n-1条边size_t size = 0;W totalW = W();UnionFindSet ufs(n);while (minqueue.size()){Edge min = minqueue.top();minqueue.pop();if (ufs.InSet(min._srci, min._dsti) == false){std::cout << _vertexs[min._srci] << "->" << _vertexs[min._dsti] << ":" << min._w << std::endl;minTree._AddEdge(min._srci, min._dsti, min._w);ufs.Union(min._srci, min._dsti);++size;totalW += min._w;}else{std::cout << "构成环:";std::cout << _vertexs[min._srci] << "->" << _vertexs[min._dsti] << ":" << min._w << std::endl;}}if (size == n - 1)return totalW;elsereturn W();}};
}

三、Prim算法

与Kruskal算法类似,Prim 算法也是23.1节所讨论的通用最小生成树算法的一个特例。Prim 算法的工作原理与Dijkstra的最短路径算法相似(该算法将在24.3节中讨论)。Prim算法所具有的一个性质是集合A中的边总是构成一裸树。如图23-5所示,这梯树从一个任意的根结点r开始,一直长大到覆盖V中的所有结点时为止。算法每一步在连接集合A和A之外的结点的所有边中,选择一条轻量级边加入到A中。根据推论23.2,这条规则所加人的边都是对A安全的边。因此,当算法终止时,A中的边形成一棵最小生成树。本策略也属于贪心策略,因为每一步所加人的边都必须是使树的总权重增加量最小的边。

在这里插入图片描述

代码实现:

// 临接矩阵
namespace Matrix
{template <class V, class W, W MAX_W = INT_MAX, bool Direction = false>class Graph{typedef Graph<V, W, MAX_W, Direction> Self;private:std::vector<V> _vertexs;             // 顶点集合std::map<V, size_t> _vIndexMap;      // 顶点的下标映射关系std::vector<std::vector<W>> _matrix; // 存储边集合的矩阵W Prim(Self &minTree, const V &v){minTree._vertexs = _vertexs;minTree._vIndexMap = _vIndexMap;int n = _vertexs.size();minTree._matrix.resize(n);for (int i = 0; i < n; i++){minTree._matrix[i].resize(n, MAX_W);}size_t srci = GetVertexIndex(v);// 标记数组,将顶点分为两个部分,一个是一个加入最小生成树的部分,一个是未加入的std::vector<bool> X(n, false);std::vector<bool> Y(n, true);X[srci] = true;Y[srci] = false;std::priority_queue<Edge, std::vector<Edge>, std::greater<Edge>> minq;for (size_t i = 0; i < n; i++){if (_matrix[srci][i] != MAX_W){minq.push({srci, i, _matrix[srci][i]});}}size_t size = 0;W totalW = W();while (minq.size()){Edge min = minq.top();minq.pop();size_t srci = min._srci;size_t dsti = min._dsti;if (X[min._dsti]){std::cout << "构成环:";std::cout << _vertexs[srci] << "->" << _vertexs[dsti] << ":" << _matrix[srci][dsti] << std::endl;}else{minTree._AddEdge(srci, dsti, _matrix[srci][dsti]);std::cout << _vertexs[srci] << "->" << _vertexs[dsti] << ":" << min._w << std::endl;X[dsti] = true;Y[dsti] = false;++size;totalW += _matrix[srci][dsti];if (size == n - 1)break;for (size_t i = 0; i < n; i++){if (_matrix[dsti][i] != MAX_W && Y[i]){minq.push({dsti, i, _matrix[dsti][i]});}}}}if (size == n - 1){return totalW;}elsereturn W();}};
}

测试代码:

void TestGraphMinTree()
{const char str[] = "abcdefghi";Graph<char, int> g(str, strlen(str));g.AddEdge('a', 'b', 4);g.AddEdge('a', 'h', 8);// g.AddEdge('a', 'h', 9);g.AddEdge('b', 'c', 8);g.AddEdge('b', 'h', 11);g.AddEdge('c', 'i', 2);g.AddEdge('c', 'f', 4);g.AddEdge('c', 'd', 7);g.AddEdge('d', 'f', 14);g.AddEdge('d', 'e', 9);g.AddEdge('e', 'f', 10);g.AddEdge('f', 'g', 2);g.AddEdge('g', 'h', 1);g.AddEdge('g', 'i', 6);g.AddEdge('h', 'i', 7);Graph<char, int> kminTree;std::cout << "Kruskal:" << g.Kruskal(kminTree) << std::endl;kminTree.Print();std::cout << std::endl<< std::endl;Graph<char, int> pminTree;std::cout << "Prim:" << g.Prim(pminTree, 'a') << std::endl;pminTree.Print();std::cout << std::endl;for (size_t i = 0; i < strlen(str); ++i){std::cout << "Prim:" << g.Prim(pminTree, str[i]) << std::endl;}
}

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

华为云征文|基于Flexus云服务器X实例的应用场景-部署脚手架开源项目若依

&#x1f534;大家好&#xff0c;我是雄雄&#xff0c;欢迎关注微信公众号&#xff1a;雄雄的小课堂 先看这里 写在前面**Flexus X实例**的云服务器简介环境准备若依项目拉取导入数据库启动本地项目&#xff08;后端&#xff09;启动本地项目&#xff08;前端&#xff09;打包后…

Linux——性能调优工具一览

一、CPU 1.调优工具 根据指标找工具 性能指标工具说明 平均负载 uptime、top uptime最简单、top提供了更全的指标 系统整体CPU使用率 vmstat、mpstat、top、sar、/proc/stat top、vmstat、mpstat只可以动态查看&#xff0c;而sar还可以记录历史数据 /proc/stat是其他性…

【知识图谱】4、LLM大模型结合neo4j图数据库实现AI问答的功能

昨天写了一篇文章&#xff0c;使用fastapi直接操作neo4j图数据库插入数据的例子&#xff0c; 本文实现LLM大模型结合neo4j图数据库实现AI问答功能。 废话不多说&#xff0c;先上代码 import gradio as gr from fastapi import FastAPI, HTTPException, Request from pydantic…

HarmonyOS开发实战( Beta5版)耗时分析器Time Profiler实践指导

DevEco Studio集成的DevEco Profiler性能调优工具&#xff08;以下简称为Profiler&#xff09;&#xff0c;提供Time、Allocation、Snapshot、CPU等场景化分析任务类型。开发应用或服务过程中&#xff0c;如果遇到卡顿、加载耗时等性能问题&#xff0c;开发者通常会关注相关函数…

机器学习周报(8.26-9.1)

文章目录 摘要Abstractself-attetionQKV理解如何让self-attention更有效local attention/truncated attention方法stride attention方法Global Attention方法data driving方法Clusteringsinkhorn sorting network选取representative keys减少Keys数量的方法self-attentionSynth…

jQuery库

注明&#xff1a;本文参考自&#xff1a;jQuery - 白月黑羽 (byhy.net) jQuery安装 Download jQuery | jQuery下载到本地 ps: script标签中的src属性&#xff1a;表示包含要执行的代码的外部文件位置 <!DOCTYPE html> <html lang"en"><head><s…

让自家的智能语音助手实现todo任务的添加

我家的树莓派在成为了“智能语音助手”后&#xff0c;经过rasa学习训练&#xff0c;已经可以帮忙查日期/时间&#xff0c;查天气预报&#xff0c;进行一些简单的闲聊。但是&#xff0c;我希望它的功能还可以再强大些&#xff0c;比如说&#xff0c;可以帮我记录todo任务。为了实…

当网络适配器的Wireless出现感叹号

1.出现如下情况 链接&#xff1a; &#xff1a;一招搞定Intel(R) Wireless-AC 9560显示感叹号&#xff0c;无法打开wifi模块&#xff01;_intel(r)wireless-ac9560感叹号-CSDN博客z 重点&#xff1a; 原因是因为电脑静电的问题。

生产es所有节点全部掉线 排查

生产es所有节点全部掉线 查看message日志发现 内存溢出 修改jvm的改小 清理buff/cache sync && echo 1 > /proc/sys/vm/drop_caches sync && echo 2 > /proc/sys/vm/drop_caches sync && echo 3 > /proc/sys/vm/drop_caches 把es内存的…

Bean 的生命周期

什么是Bean的生命周期 Bean 的生命周期就是&#xff1a;对象从创建开始到最终销毁的整个过程&#xff0c;Bean 对象从创建到销毁中经历了哪些过程 什么时候创建Bean对象&#xff1f;创建Bean对象的前后会调用什么方法&#xff1f;Bean对象什么时候销毁&#xff1f;Bean对象的销…

13-springcloud gateway集成nacos实现负载均衡

网关作为访问系统的入口&#xff0c;负载均衡是必选项而不是可选项&#xff0c;本文介绍gateway与nacos集成&#xff0c;实现负载均衡的过程。关于springcloud gateway的基本用法&#xff0c;同学可以看看上篇文章: 12-使用gateway作为网关。 0、环境 jdk&#xff1a;1.8spri…

idea插件开发的第一天-写一个小Demo

介绍 Demo说明 本文基于maven项目开发,idea版本为2022.3以上,jdk为1.8本文在Tools插件之上进行开发 Tools插件说明 Tools插件是一个Idea插件,此插件提供统一Spi规范,极大的降低了idea插件的开发难度,并提供开发者模块,可以极大的为开发者开发此插件提供便利Tools插件安装需…

LLM系列 | 36:Google最新开源大模型:Gemma 2介绍及其微调(下篇)

引言 环境安装 数据准备 下载 处理 模型训练 模型inference 结果 gemma-2-9b gemma-2-9b-it 引言 低头观落日&#xff0c;引手摘飞星。 小伙伴们好&#xff0c;我是微信公众号《小窗幽记机器学习》的小编&#xff1a;卖黑神话的小女孩。本文紧接前文Google最新开源大…

栈和队列——用队列实现栈

题目中给出&#xff0c;让我们应用两个队列实现栈&#xff0c;首先我们先来想一下&#xff0c;栈是先进后出&#xff0c;队列是先进先出。所以我们就需要应用两个队列来回导才能实现栈的特点。因为这道题是基于队列来实现的&#xff0c;所以在下方若有看不懂的函数名称可以去栈…

【indirect 函数 ★二级下拉菜单】

Indirect 函数 &#x1f33c;indirect函数参数&#x1f33c;应用&#xff1a;&#x1f33c;跨表引用同一单元格&#x1f33c;二级下拉列表 &#x1f33c;indirect函数参数 返回⬅️【文本字符串所指定的引用】 INDIRECT(ref_text,[a1]) 其中【ref_text】是引用的文本 [a1] 是…

网络安全实训六(靶机实例DC-3)

1 信息收集 1.1 获取靶机IP 1.2 扫描靶机网站的目录 1.3 扫描端口和服务器信息 1.4 进入网站 1.5 在msf中给搜索joomla扫描器 1.6 设置参数查看joomla版本信息 1.7 按照版本号搜索漏洞 1.8 查看漏洞使用 2 渗透 2.1 查看是否存在SQL注入 2.2 获取到数据库信息 2.3 爆破列表 2…

盘点java8 stream中隐藏的函数式接口

shigen坚持更新文章的博客写手&#xff0c;记录成长&#xff0c;分享认知&#xff0c;留住感动。个人IP&#xff1a;shigen 提到函数式接口&#xff0c;最常见的就是lambda表达式&#xff0c;IDEA也有智能的提示&#xff1a; 最后改成这样的就是最简洁的、IDEA希望的风格&#…

【我要成为配环境高手】Visual Studio中Qt安装与配置(无伤速通)

1.下载安装Qt和VSIX插件 2.本地环境变量配置 添加如下&#xff1a; D:\ProgramData\Qt\Qt5.14.2\5.14.2\msvc2017_64\libD:\ProgramData\Qt\Qt5.14.2\5.14.2\msvc2017_64\bin3.VS配置 ⭐项目右键->属性->调试->环境&#xff0c;添加如下&#xff1a;(很重要&#x…

随笔十、音频扩展模块测试

本项测试简单&#xff0c;对购买的音频扩展模块进行录音放音测试 按照使用说明&#xff0c;连接音频小板&#xff0c;一个喇叭一个麦克风&#xff0c;4根线&#xff0c;buildroot系统镜像 录音测试 rootRK356X:/# arecord -c 1 -r 44100 -f S16_LE /tmp/record.wav Recording …

【面试五】PID控制算法

一、 PID算法简介 PID&#xff08;Proportional-Integral-Derivative&#xff09;控制算法是一种经典的反馈控制方法&#xff0c;广泛应用于自动控制系统&#xff0c;例如温度控制、速度控制、位置控制等。 PID控制算法的核心包含三个部分&#xff1a;比例项&#xff08;P&…