基于C#实现Prim算法

图论在数据结构中是非常有趣而复杂的,作为 Web 码农的我,在实际开发中一直没有找到它的使用场景,不像树那样的频繁使用,不过还是准备仔细的把图论全部过一遍。

一、最小生成树

图中有一个好玩的东西叫做生成树,就是用边来把所有的顶点联通起来,前提条件是最后形成的联通图中不能存在回路,所以就形成这样一个推理:假设图中的顶点有 n 个,则生成树的边有 n-1 条,多一条会存在回路,少一路则不能把所有顶点联通起来,如果非要在图中加上权重,则生成树中权重最小的叫做最小生成树。
image.png
对于上面这个带权无向图来说,它的生成树有多个,同样最小生成树也有多个,因为我们比的是权重的大小。

二、Prim 算法

求最小生成树的算法有很多,常用的是 Prim 算法和 Kruskal 算法,为了保证单一职责,我把 Kruskal 算法放到下一篇,那么 Prim 算法的思想是什么呢?很简单,贪心思想。
如上图:现有集合 M={A,B,C,D,E,F},再设集合 N={}。

  • 第一步:挑选任意节点(比如 A),将其加入到 N 集合,同时剔除 M 集合的 A。
  • 第二步:寻找 A 节点权值最小的邻节点(比如 F),然后将 F 加入到 N 集合,此时 N={A,F},同时剔除 M 集合中的 F。
  • 第三步:寻找{A,F}中的权值最小的邻节点(比如 E),然后将 E 加入到 N 集合,此时 N={A,F,E},同时剔除 M 集合的 E。
  • 。。。

最后 M 集合为{}时,生成树就构建完毕了,是不是非常的简单,这种贪心做法我想大家都能想得到,如果算法配合一个好的数据结构,就会如虎添翼。

三、代码

1、图的存储

图的存储有很多方式,邻接矩阵,邻接表,十字链表等等,当然都有自己的适合场景,下面用邻接矩阵来玩玩,邻接矩阵需要采用两个数组,
①. 保存顶点信息的一维数组,
②. 保存边信息的二维数组。

 public class Graph{/// <summary>/// 顶点个数/// </summary>public char[] vertexs;/// <summary>/// 边的条数/// </summary>public int[,] edges;/// <summary>/// 顶点个数/// </summary>public int vertexsNum;/// <summary>/// 边的个数/// </summary>public int edgesNum;}

2、矩阵构建

矩阵构建很简单,这里把上图中的顶点和权的信息保存在矩阵中。

 #region 矩阵的构建/// <summary>/// 矩阵的构建/// </summary>public void Build(){//顶点数graph.vertexsNum = 6;//边数graph.edgesNum = 8;graph.vertexs = new char[graph.vertexsNum];graph.edges = new int[graph.vertexsNum, graph.vertexsNum];//构建二维数组for (int i = 0; i < graph.vertexsNum; i++){//顶点graph.vertexs[i] = (char)(i + 65);for (int j = 0; j < graph.vertexsNum; j++){graph.edges[i, j] = int.MaxValue;}}graph.edges[0, 1] = graph.edges[1, 0] = 80;graph.edges[0, 3] = graph.edges[3, 0] = 100;graph.edges[0, 5] = graph.edges[5, 0] = 20;graph.edges[1, 2] = graph.edges[2, 1] = 90;graph.edges[2, 5] = graph.edges[5, 2] = 70;graph.edges[3, 2] = graph.edges[2, 3] = 100;graph.edges[4, 5] = graph.edges[5, 4] = 40;graph.edges[3, 4] = graph.edges[4, 3] = 60;graph.edges[2, 3] = graph.edges[3, 2] = 10;}#endregion

3、Prim

要玩 Prim,我们需要两个字典。
①:保存当前节点的字典,其中包含该节点的起始边和终边以及权值,用 weight=-1 来记录当前节点已经访问过,用 weight=int.MaxValue 表示两节点没有边。
②:输出节点的字典,存放的就是我们的 N 集合。
当然这个复杂度玩高了,为 O(N2),寻找 N 集合的邻边最小权值时,我们可以玩玩 AVL 或者优先队列来降低复杂度。

 #region prim算法/// <summary>/// prim算法/// </summary>public Dictionary<char, Edge> Prim(){Dictionary<char, Edge> dic = new Dictionary<char, Edge>();//统计结果Dictionary<char, Edge> outputDic = new Dictionary<char, Edge>();//weight=MaxValue:标识没有边for (int i = 0; i < graph.vertexsNum; i++){//起始边var startEdge = (char)(i + 65);dic.Add(startEdge, new Edge() { weight = int.MaxValue });}//取字符的开始位置var index = 65;//取当前要使用的字符var start = (char)(index);for (int i = 0; i < graph.vertexsNum; i++){//标记开始边已使用过dic[start].weight = -1;for (int j = 1; j < graph.vertexsNum; j++){//获取当前 c 的 邻边var end = (char)(j + index);//取当前字符的权重var weight = graph.edges[(int)(start) - index, j];if (weight < dic[end].weight){dic[end] = new Edge(){weight = weight,startEdge = start,endEdge = end};}}var min = int.MaxValue;char minkey = ' ';foreach (var key in dic.Keys){//取当前 最小的 key(使用过的除外)if (min > dic[key].weight && dic[key].weight != -1){min = dic[key].weight;minkey = key;}}start = minkey;//边为顶点减去1if (outputDic.Count < graph.vertexsNum - 1 && !outputDic.ContainsKey(minkey)){outputDic.Add(minkey, new Edge(){weight = dic[minkey].weight,startEdge = dic[minkey].startEdge,endEdge = dic[minkey].endEdge});}}return outputDic;}#endregion

4、最后我们来测试一下,看看找出的最小生成树。

 public static void Main(){MatrixGraph martix = new MatrixGraph();martix.Build();var dic = martix.Prim();Console.WriteLine("最小生成树为:");foreach (var key in dic.Keys){Console.WriteLine("({0},{1})({2})", dic[key].startEdge, dic[key].endEdge, dic[key].weight);}Console.Read();}

image.png

 using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Diagnostics;using System.Threading;using System.IO;using SupportCenter.Test.ServiceReference2;using System.Threading.Tasks;namespace ConsoleApplication2{public class Program{public static void Main(){MatrixGraph martix = new MatrixGraph();martix.Build();var dic = martix.Prim();Console.WriteLine("最小生成树为:");foreach (var key in dic.Keys){Console.WriteLine("({0},{1})({2})", dic[key].startEdge, dic[key].endEdge, dic[key].weight);}Console.Read();}}/// <summary>/// 定义矩阵节点/// </summary>public class MatrixGraph{Graph graph = new Graph();public class Graph{/// <summary>/// 顶点个数/// </summary>public char[] vertexs;/// <summary>/// 边的条数/// </summary>public int[,] edges;/// <summary>/// 顶点个数/// </summary>public int vertexsNum;/// <summary>/// 边的个数/// </summary>public int edgesNum;}#region 矩阵的构建/// <summary>/// 矩阵的构建/// </summary>public void Build(){//顶点数graph.vertexsNum = 6;//边数graph.edgesNum = 8;graph.vertexs = new char[graph.vertexsNum];graph.edges = new int[graph.vertexsNum, graph.vertexsNum];//构建二维数组for (int i = 0; i < graph.vertexsNum; i++){//顶点graph.vertexs[i] = (char)(i + 65);for (int j = 0; j < graph.vertexsNum; j++){graph.edges[i, j] = int.MaxValue;}}graph.edges[0, 1] = graph.edges[1, 0] = 80;graph.edges[0, 3] = graph.edges[3, 0] = 100;graph.edges[0, 5] = graph.edges[5, 0] = 20;graph.edges[1, 2] = graph.edges[2, 1] = 90;graph.edges[2, 5] = graph.edges[5, 2] = 70;graph.edges[3, 2] = graph.edges[2, 3] = 100;graph.edges[4, 5] = graph.edges[5, 4] = 40;graph.edges[3, 4] = graph.edges[4, 3] = 60;graph.edges[2, 3] = graph.edges[3, 2] = 10;}#endregion#region 边的信息/// <summary>/// 边的信息/// </summary>public class Edge{//开始边public char startEdge;//结束边public char endEdge;//权重public int weight;}#endregion#region prim算法/// <summary>/// prim算法/// </summary>public Dictionary<char, Edge> Prim(){Dictionary<char, Edge> dic = new Dictionary<char, Edge>();//统计结果Dictionary<char, Edge> outputDic = new Dictionary<char, Edge>();//weight=MaxValue:标识没有边for (int i = 0; i < graph.vertexsNum; i++){//起始边var startEdge = (char)(i + 65);dic.Add(startEdge, new Edge() { weight = int.MaxValue });}//取字符的开始位置var index = 65;//取当前要使用的字符var start = (char)(index);for (int i = 0; i < graph.vertexsNum; i++){//标记开始边已使用过dic[start].weight = -1;for (int j = 1; j < graph.vertexsNum; j++){//获取当前 c 的 邻边var end = (char)(j + index);//取当前字符的权重var weight = graph.edges[(int)(start) - index, j];if (weight < dic[end].weight){dic[end] = new Edge(){weight = weight,startEdge = start,endEdge = end};}}var min = int.MaxValue;char minkey = ' ';foreach (var key in dic.Keys){//取当前 最小的 key(使用过的除外)if (min > dic[key].weight && dic[key].weight != -1){min = dic[key].weight;minkey = key;}}start = minkey;//边为顶点减去1if (outputDic.Count < graph.vertexsNum - 1 && !outputDic.ContainsKey(minkey)){outputDic.Add(minkey, new Edge(){weight = dic[minkey].weight,startEdge = dic[minkey].startEdge,endEdge = dic[minkey].endEdge});}}return outputDic;}#endregion}}

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

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

相关文章

ES 万条以外分页检索功能实现及注意事项

背景 以 ES 存储日志&#xff0c;且需要对日志进行分页检索&#xff0c;当数据量过大时&#xff0c;就面临 ES 万条以外的数据检索问题&#xff0c;如何利用滚动检索实现这个需求呢&#xff1f;本文介绍 ES 分页检索万条以外的数据实现方法及注意事项。 需求分析 用 ES 存储数…

css图片缩放属性object-fit说明

object-fit 属性可以设置以下值&#xff1a; 属性值说明例子fill填充容器&#xff0c;可能会改变图片的比例。object-fit: fill;contain保持图片的原始比例&#xff0c;确保图片完全包含在容器内。object-fit: contain;cover保持图片的原始比例&#xff0c;确保图片覆盖整个容…

性能优化中使用Profiler进行页面卡顿的排查及解决方式

文章目录 一、前言二、页面卡顿的排查方式1、耗时操作的监控2、页面卡顿的监控 三、参考链接 一、前言 程序的优化在做过线上bug处理&#xff0c;布局层级优化&#xff0c;项目依赖库版本更新&#xff0c;重复库合并&#xff0c;删除未使用的资源&#xff0c;删除冗余的库&…

机器学习【01】相关环境的安装

学习实例 参考资料&#xff1a;联邦学习实战{杨强}https://book.douban.com/subject/35436587/ 项目地址&#xff1a;https://github.com/FederatedAI/Practicing-Federated-Learning/tree/main/chapter03_Python_image_classification 一、环境准备 GPU安装CUDA、cuDNN pytho…

PHP 语法||PHP 变量

PHP 脚本在服务器上执行&#xff0c;然后将纯 HTML 结果发送回浏览器。 基本的 PHP 语法 PHP 脚本可以放在文档中的任何位置。 PHP 脚本以 <?php 开始&#xff0c;以 ?> 结束&#xff1a; <?php // PHP 代码 ?> 值得一提的是&#xff0c;通过设定php.ini的相…

nvm-切换node版本工具安装-方便好用

去官网下载&#xff1a; https://github.com/coreybutler/nvm-windows#installation--upgrades 网站进去后点击下载&#xff0c;点击那个exe文件就下载本地&#xff0c;然后双击安装 安装nvm 就直接按照窗口提示的下一步就行&#xff0c;如果改了某些地方会不成功&#xf…

数字孪生技术:提升UI交互性与个性化设计

随着数字化时代的到来&#xff0c;数字孪生技术正在逐渐改变我们的生活和工作方式。数字孪生是一种复制现实世界系统或实体的技术&#xff0c;通过创建数字模型来模拟现实世界中的各种行为和事件。这种技术不仅为人们提供了一个全新的视角来看待和解决问题&#xff0c;同时也为…

内衣专用洗衣机怎么样?口碑最好的小型洗衣机

随着人们的生活水平的提升&#xff0c;越来越多小伙伴来开始追求更高的生活水平&#xff0c;一些智能化的小家电就被发明出来&#xff0c;而且内衣洗衣机是其中一个。现在通过内衣裤感染到细菌真的是越来越多&#xff0c;所以我们对内衣裤的清洗频次会高于普通衣服&#xff0c;…

Spring Boot 3.2发布:大量Java 21的支持上线,改进可观测性

就在今天凌晨&#xff0c;Spring Boot 3.2正式发布了&#xff01;该版本是在Java 21正式发布之后的重要支持版本&#xff0c;所以在该版本中包含大量对Java 21支持的优化。 下面&#xff0c;我们分别通过Spring官方发布的博文和Josh Long长达80分钟的介绍视频&#xff0c;一起…

飞翔的鸟游戏

一.准备工作 首先创建一个新的Java项目命名为“飞翔的鸟”&#xff0c;并在src中创建一个包命名为“com.qiku.bird"&#xff0c;在这个包内分别创建4个类命名为“Bird”、“BirdGame”、“Column”、“Ground”&#xff0c;并向需要的图片素材导入到包内。 二.代码呈现 pa…

【医学图像处理】超详细!PET图像批量预处理

目录 一、单个PET图像预处理1、使用[MRIConvert](https://pan.baidu.com/s/1cn3kgeVRir8HvP6HHm0M0Q?pwd5rt5)处理DCM2、MRI和PET数据预处理过程1&#xff09; 打开matlab命令行输入spm pet&#xff0c;打开SMP12&#xff0c;界面如下2&#xff09; Realign&#xff0c;只需要…

【Vue】插值表达式

作用&#xff1a;利用表达式进行插值渲染 语法&#xff1a;{ { 表达式 } } 目录 案例一&#xff1a; 案例二&#xff1a; 案例三&#xff1a; ​编辑 注意&#xff1a; 案例一&#xff1a; <!DOCTYPE html> <html lang"en"> <head><me…

项目中如何配置数据可视化展现

在现今数据驱动的时代&#xff0c;可视化已逐渐成为数据分析的主要途径&#xff0c;可视化大屏的广泛使用便应运而生。很多公司及政务机构&#xff0c;常利用大屏的手段展现其实力或演示业务&#xff0c;可视化的效果能让观者更快速的理解结果并直观的看到数据展现。因此&#…

加速软件开发:自动化测试在持续集成中的重要作用!

持续集成的自动化测试 如今互联网软件的开发、测试和发布&#xff0c;已经形成了一套非常标准的流程&#xff0c;最重要的组成部分就是持续集成&#xff08;Continuous integration&#xff0c;简称CI&#xff0c;目前主要的持续集成系统是Jenkins&#xff09;。 那么什么是持…

教育+AIGC开局之年:教育派作业帮、科技派科大讯飞同路不同道

配图来自Canva可画 与往年相比&#xff0c;今年的双11显得格外冷清&#xff0c;GMV&#xff08;商品交易总额&#xff09;数据和增长数据无人提及&#xff0c;京东、淘宝天猫、抖音、快手等平台的火药味都淡了。一片祥和有序的双11氛围中&#xff0c;昔日的K12教育企业与科技企…

清华大学提出全新加速训练大模型方法SoT

近日&#xff0c;微软研究和清华大学的研究人员共同提出了一种名为“Skeleton-of-Thought&#xff08;SoT&#xff09;”的全新人工智能方法&#xff0c;旨在解决大型语言模型(LLMs)生成速度较慢的问题。 尽管像GPT-4和LLaMA等LLMs在技术领域产生了深远影响&#xff0c;但其处…

提供电商数据|带你简单认识天猫API接口相关参数文档调用说明

什么是API接口 API接口(Application Programming Interface Interface)是应用程序与开发人员或其他程序互相通信的方式。它允许开发者访问应用程序的数据和功能。 API接口,软件的“握手”与“交流”之道,软件世界的“好基友”。想让软件聊得来?想开发App却无从下手?API来相救…

【腾讯云云上实验室-向量数据库】Tencent Cloud VectorDB为非结构化数据查询插上飞翔的翅膀——以企业知识库为例

前言 以前我曾疑惑&#xff0c;对于非结构化的内容&#xff0c;如一张图片或一段视频&#xff0c;如何实现搜索呢&#xff1f;图片或视频作为二进制文件&#xff0c;我们如何将其转化为可搜索的数据并存储起来&#xff0c;然后在搜索时将其还原呢&#xff1f; 后来我发现&…

Tomcat 配置

1&#xff1a; 打开 2&#xff1a;选择版本号&#xff0c;我这边是 1.7 3&#xff1a;添加 web 4: 添加jar包 5&#xff1a;添加 6&#xff1a;添加 Tomcat