最小生成树:Prim算法

部署运行你感兴趣的模型镜像

讲构建最小生成树的算法前,先来回顾一下什么是生成树,什么是最小生成树?生成树是指:在一个连通图Graph中,包含Graph中所有n个顶点的极小连通子图,一定包含Graph中的n-1条边(如果小于n-1条边,生成树会不连通。如果大于n-1条边,就一定会产生回路,那么就不是树了,树中不能产生回路)。且生成树不唯一。举个例子:

这个无向连通图的生成树分别有

 

什么是最小生成树?

  1. 无回路,且包含原图中的n-1条边。
  2. 包含原图中的全部顶点。
  3. 边的权重和在所有其他生成树中最小。
  4. 最小生成树存在,则该图一定连通。反过来一样,图连通,则最小生成树一定存在。

那么如何构建满足以上条件的生成树?这篇日志先介绍其中一种常用的普里姆(Prim)算法。Prim算法构建最小生成树,简单来说就是在图中,从某一顶点出发,逐步构建,让一棵小树逐渐长大。用一个例子来说明更清晰点吧!首先看下面一张无向网图:

要构造这张图的最小生成树,首先,假设我们从V0顶点开始出发,也就是以V0为根结点开始建树,接着往外扩展,从与V0顶点相邻的顶点中找出权值最小的顶点,可以看到是V6,所以把V6和V0连接起来。

也就是把V6收录进了这棵最小生成树中了。接着继续,从当前树中顶点的邻接点中(也就是V0和V6的邻接点中,找出权值最小的顶点)。可以看到是V1,所以把V1也接入最小生成树中。

然后继续,到V2结点,也接入最小生成树中

因为不能形成回路,所以V2和V6之间不能连接(虽然权值最小,等于3)。V0和V1之间也不能连接。所以只能V6和V4连接

最后V4和V5连接,V4再和V3连接,就完成了这棵最小生成树的构建了。

(最小生成树)

以上就是Prim算法构建最小生成树的过程。接下来看怎么用代码实现这个算法:

首先传进去我们的图MyGraph,和一个MST图,MST图用来存最小生成树。然后定义 两个一维数组dist和parent,

· parent数组存的是某个顶点的(下标表示)父结点parent[0]=-1表示V0为根结点。

· dist数组用来保存顶点Vj到VT顶点的边的最小权值(也就是某个结点到最小生成树MST的最小 距离),即存储各顶点与当前树的"距离".如果Vj属于当前树,则dist[j]=0;。

然后是变量TotalWeight保存最小生成树的权重和。Vcount保存收录的顶点的个数,以及一条边E后面做构建生成树时插入顶点用。

这些变量都定义完后,就要开始对它们进行初始化。第142行开始初始化dist数组,默认初始点下标是0,也就是顶点V0到各个顶点的距离。初始化parent数组,暂时定义所有顶点的父结点都是初始点0,因为V0是根节点,一开始就它一个。权重和TotalWeight和收录的顶点个数Vcount都初始化为0。

然后初始化最小生成树MST图,就跟初始化一个新图一样,创建有Vertex个顶点但没有边的图(还是用邻接矩阵的方式)。第154行建立一个空的边结点,后面做树生长时插入顶点用。

初始化工作做完后,接着开始建树了(第157行开始),首先是初始点0(假设从V0顶点开始),把V0顶点收录进MST,因为结点V0是根结点,所以到最小生成树的距离更新为0(即dist[0]=0)。收录的顶点数Vcount++。parent[0]=-1是因为V0是根结点。

根结点处理好后,就要开始让小树生长了。我们可以用一个while循环,不断找出当前最小生成树的所有邻接点中“距离”最近的(也就是权值最小)的顶点,找到一个就把它插入进MST里,让最小生成树“生长”。那么循环什么时候结束?当然就是(第165行),当这个顶点找不到的时候就break退出while循环。

我们来看第163行开始,用一个FindMinDist函数找出未被收录的结点中距离当前树"距离"(即权值)最小的顶点赋给V。然后将V及相应的边 <parent[V], V>收录进MST(也就是说将顶点V和V的父结点插入到最小生成树中)。第176行,插入完这个新顶点后,更新TotalWeight权值和。以及结点V到最小生成树的距离更新为0(因为这个顶点已经融入到最小生成树当中了)。Vcount++表示收录到的顶点数加一。

   循环的最后一步就是扫描图上所有顶点,找出跟V相邻的顶点,V的邻接点,且是没被收录进最小生成树中的V的邻接点(dist[W]!=0即没被收录进最小生成树中,MyGraph->[V][W]<INFINITY即W是V邻接点)。第185行如果收录了V后能使得dist[W]变小,那么就更新一下dist[W]。

最后的最后,在执行完Prim算法的最后一步,就是判断下最小生成树MST中的顶点个数有没有达到原图中的顶点个数。如果没有达到,证明这个图不连通,就返回ERROR。构建成功就返回最小生成树的权重和TotalWeight。

还有一个函数FindMinDist函数要怎么做呢?

FindMinDist函数找出未被收录的顶点中dist最小值(即未被收录的顶点中距离当前最小生成树"距离"最短的顶点)。我们把原图MyGraph和dist数组传进去,定义两个变量MinIndex和V,MinIndex保存最小顶点的下标,初始化它为INFINITY。找未被收录的顶点中dist最小的顶点,就用一个循环扫描图中所有顶点,如果顶点没被收录,且顶点值小于MinDist的,就更新一下MinDist,并且把下标V更新给MinIndex。如果能够找到dist最小顶点的话,就把MinIndex返回出去,否则返回ERROR。

最后看下用邻接矩阵方式的Prim算法效果图:

 

您可能感兴趣的与本文相关的镜像

Stable-Diffusion-3.5

Stable-Diffusion-3.5

图片生成
Stable-Diffusion

Stable Diffusion 3.5 (SD 3.5) 是由 Stability AI 推出的新一代文本到图像生成模型,相比 3.0 版本,它提升了图像质量、运行速度和硬件效率

### ROSYOLO结合的人脸识别算法实现教程 #### 一、背景介绍 在计算机视觉领域,人脸识别是一项基础而重要的技术。通过结合ROS(Robot Operating System)和YOLO(You Only Look Once),可以在机器人系统中实现实时的目标检测功能。YOLO作为一种高效的实时目标检测框架,在嵌入式设备上的应用非常广泛[^1]。 #### 二、YOLOv5的工作原理 YOLOv5是一种基于深度学习的目标检测算法,其核心思想是将输入图像划分为多个网格,并预测每个网格内的边界框及其类别概率。该模型具有较高的推理速度和准确性,适合用于资源受限的场景。具体来说,YOLOv5的主要特点包括单阶段检测、锚点优化以及自适应计算能力调整[^3]。 #### 三、ROS环境下的部署步骤 为了在ROS环境中成功部署YOLOv5并完成人脸识别任务,以下是详细的实施过程: ##### 1. 创建虚拟环境 建议使用`conda`或`virtualenv`工具创建独立的Python开发环境,以避免依赖冲突。例如: ```bash conda create -n ros_yolo python=3.8 source activate ros_yolo ``` ##### 2. 安装必要库 确保安装了以下关键组件: - `torch`: PyTorch机器学习框架。 - `opencv-python`: OpenCV图像处理库。 - `ros-pkg-name`: 对应版本的ROS包管理器。 可以通过pip命令快速安装所需模块: ```bash pip install torch torchvision opencv-python-headless onnxruntime-gpu sudo apt-get update && sudo apt-get install ros-$ROS_DISTRO-cv-bridge ``` ##### 3. 获取YOLOv5源码 克隆官方仓库至本地目录: ```bash git clone https://github.com/ultralytics/yolov5.git cd yolov5 pip install -r requirements.txt ``` ##### 4. 配置ROS节点 编写一个简单的ROS订阅者节点来接收摄像头数据流并将帧传递给YOLOv5模型进行推断。下面展示了一个简化版的例子: ```python #!/usr/bin/env python3 import rospy from sensor_msgs.msg import Image from cv_bridge import CvBridge, CvBridgeError import cv2 import numpy as np import torch from yolov5.models.experimental import attempt_load class FaceDetectorNode: def __init__(self): self.bridge = CvBridge() self.image_subscriber = rospy.Subscriber("/camera/image_raw", Image, self.callback) self.model = attempt_load('yolov5s.onnx', map_location=torch.device('cuda')) # 加载ONNX模型 def callback(self, data): try: frame = self.bridge.imgmsg_to_cv2(data, "bgr8") # 转换为OpenCV格式 except CvBridgeError as e: print(e) results = self.model(frame) # 推理结果 bboxes = results.xyxy[0].cpu().numpy() # 提取边框坐标 for bbox in bboxes: x_min, y_min, x_max, y_max, conf, cls_id = bbox.astype(int) label = f'Face {conf:.2f}' cv2.rectangle(frame, (x_min, y_min), (x_max, y_max), (0, 255, 0), 2) cv2.putText(frame, label, (x_min, y_min - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.9, (0, 255, 0), 2) cv2.imshow("Detected Faces", frame) cv2.waitKey(1) if __name__ == '__main__': rospy.init_node('face_detector') detector = FaceDetectorNode() rospy.spin() ``` 此代码片段实现了从相机主题读取消息的功能,并调用了预先训练好的YOLOv5 ONNX模型来进行人脸定位。 #### 四、总结 上述方法提供了一种有效途径,能够利用ROS平台集成先进的深度学习算法——如YOLOv5——从而增强自主系统的感知能力。值得注意的是,实际操作过程中可能遇到硬件性能瓶颈或者兼容性问题,因此需要针对特定需求做适当调整[^2]。 ---
评论 16
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值