算法学习5——图算法

图算法在计算机科学中占有重要地位,广泛应用于网络连接、路径查找、社会网络分析等领域。本文将介绍几种常见的图算法,包括Dijkstra算法、Bellman-Ford算法、Floyd-Warshall算法、Kruskal算法和Prim算法,并提供相应的Python代码示例。

图的基本概念

  • :由节点(顶点)和节点之间的边组成的集合。图可以是有向图或无向图。
  • 有向图:边有方向,即边的起点和终点是有序的。
  • 无向图:边没有方向,即边的起点和终点是无序的。
  • 权重:边可以有一个数值,表示从一个节点到另一个节点的代价或距离。

1. Dijkstra算法(最短路径)

简介:Dijkstra算法用于计算单源最短路径,即从一个起始节点到所有其他节点的最短路径。它适用于非负权重的图,通过贪心策略逐步找到最短路径。

实现过程

  1. 初始化距离数组dist,起始节点到自身的距离为0,其余为无限大。
  2. 使用优先队列(最小堆)存储节点及其当前最短距离。
  3. 每次从队列中取出距离最小的节点,更新其邻接节点的距离。
  4. 重复上述过程,直到所有节点的最短距离都被确定。

Python代码

import heapqdef dijkstra(graph, start):dist = {node: float('inf') for node in graph}dist[start] = 0priority_queue = [(0, start)]while priority_queue:current_dist, current_node = heapq.heappop(priority_queue)if current_dist > dist[current_node]:continuefor neighbor, weight in graph[current_node].items():distance = current_dist + weightif distance < dist[neighbor]:dist[neighbor] = distanceheapq.heappush(priority_queue, (distance, neighbor))return dist# 示例
graph = {'A': {'B': 1, 'C': 4},'B': {'A': 1, 'C': 2, 'D': 5},'C': {'A': 4, 'B': 2, 'D': 1},'D': {'B': 5, 'C': 1}
}
print(dijkstra(graph, 'A'))

2. Bellman-Ford算法(最短路径)

简介:Bellman-Ford算法用于计算单源最短路径,允许图中存在负权边。该算法通过反复更新边的权重来找到最短路径。

实现过程

  1. 初始化距离数组dist,起始节点到自身的距离为0,其余为无限大。
  2. 进行|V|-1次松弛操作,每次遍历所有边并更新距离。
  3. 检查是否存在负权回路,如果在第|V|次松弛操作中还能更新距离,说明存在负权回路。

Python代码

def bellman_ford(graph, start):dist = {node: float('inf') for node in graph}dist[start] = 0for _ in range(len(graph) - 1):for node in graph:for neighbor, weight in graph[node].items():if dist[node] + weight < dist[neighbor]:dist[neighbor] = dist[node] + weight# 检查负权回路for node in graph:for neighbor, weight in graph[node].items():if dist[node] + weight < dist[neighbor]:return "Graph contains a negative-weight cycle"return dist# 示例
graph = {'A': {'B': 1, 'C': 4},'B': {'A': 1, 'C': 2, 'D': 5},'C': {'A': 4, 'B': 2, 'D': 1},'D': {'B': 5, 'C': 1}
}
print(bellman_ford(graph, 'A'))

3. Floyd-Warshall算法(全对全最短路径)

简介:Floyd-Warshall算法用于计算所有节点之间的最短路径。它利用动态规划的思想,通过逐步更新路径长度来找到最短路径。

实现过程

  1. 初始化距离矩阵dist,对角线为0,其余为边的权重或无限大。
  2. 对每一对节点,检查通过中间节点的路径是否更短,若是则更新距离。
  3. 重复上述过程,直到所有节点之间的最短路径都被确定。

Python代码

def floyd_warshall(graph):nodes = list(graph.keys())dist = {node: {node2: float('inf') for node2 in nodes} for node in nodes}for node in nodes:dist[node][node] = 0for node in graph:for neighbor, weight in graph[node].items():dist[node][neighbor] = weightfor k in nodes:for i in nodes:for j in nodes:if dist[i][j] > dist[i][k] + dist[k][j]:dist[i][j] = dist[i][k] + dist[k][j]return dist# 示例
graph = {'A': {'B': 1, 'C': 4},'B': {'A': 1, 'C': 2, 'D': 5},'C': {'A': 4, 'B': 2, 'D': 1},'D': {'B': 5, 'C': 1}
}
print(floyd_warshall(graph))

4. Kruskal算法(最小生成树)

简介:Kruskal算法用于计算最小生成树(MST),即连接所有节点且总权重最小的树。该算法适用于无向加权图,通过贪心策略,每次选择权重最小的边,保证不形成环。

实现过程

  1. 初始化每个节点的父节点和秩(用于实现并查集)。
  2. 按权重升序排序所有边。
  3. 依次选择最小权重的边,若不形成环则加入生成树。
  4. 使用并查集检测环的形成。

Python代码

class UnionFind:def __init__(self, n):self.parent = list(range(n))self.rank = [0] * ndef find(self, u):if self.parent[u] != u:self.parent[u] = self.find(self.parent[u])return self.parent[u]def union(self, u, v):root_u = self.find(u)root_v = self.find(v)if root_u != root_v:if self.rank[root_u] > self.rank[root_v]:self.parent[root_v] = root_uelif self.rank[root_u] < self.rank[root_v]:self.parent[root_u] = root_velse:self.parent[root_v] = root_uself.rank[root_u] += 1def kruskal(edges, n):uf = UnionFind(n)mst = []edges.sort(key=lambda x: x[2])  # 按权重排序边for u, v, weight in edges:if uf.find(u) != uf.find(v):uf.union(u, v)mst.append((u, v, weight))return mst# 示例
edges = [(0, 1, 1),(0, 2, 4),(1, 2, 2),(1, 3, 5),(2, 3, 1)
]
n = 4  # 节点数量
print(kruskal(edges, n))

5. Prim算法(最小生成树)

简介:Prim算法也是一种用于计算最小生成树的算法,适用于连通无向加权图。它通过贪心策略,每次选择连接生成树和未访问节点的最小权重边。

实现过程

  1. 初始化距离数组dist,起始节点到自身的距离为0,其余为无限大。
  2. 使用优先队列(最小堆)存储节点及其当前最短距离。
  3. 每次从队列中取出距离最小的节点,加入生成树,并更新其邻接节点的距离。
  4. 重复上述过程,直到所有节点都被访问。

Python代码

import heapqdef prim(graph, start):mst = []visited = set()min_heap = [(0, start, None)]  # (权重, 当前节点, 父节点)while min_heap:weight, node, parent = heapq.heappop(min_heap)if node not in visited:visited.add(node)if parent is not None:mst.append((parent, node, weight))for neighbor, edge_weight in graph[node].items():if neighbor not in visited:heapq.heappush(min_heap, (edge_weight, neighbor, node))return mst# 示例
graph = {'A': {'B': 1, 'C': 4},'B': {'A': 1, 'C': 2, 'D': 5},'C': {'A': 4, 'B': 2, 'D': 1},'D': {'B': 5, 'C': 1}
}
print(prim(graph, 'A'))

这一章的图算法和上一章的动态规划,都在运筹学中运用较多。是运筹优化和决策的不二之选。

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

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

相关文章

在 WSL2 中频繁切换 PHP 版本,可以使用更简便的方法

在 WSL2 中频繁切换 PHP 版本&#xff0c;可以使用更简便的方法&#xff0c;例如使用 update-alternatives 工具。这是一种更系统化的方法&#xff0c;允许你更方便地管理和切换不同的 PHP 版本。 以下是使用 update-alternatives 工具切换 PHP 版本的步骤&#xff1a; 添加 P…

论文学习记录之一种具有边缘增强特点的医学图像分割网络

标题&#xff1a;一种具有边缘增强特点的医学图像分割网络 期刊&#xff1a;电子与信息学报-&#xff08;2022年5月出刊&#xff09; 摘要&#xff1a;针对传统医学图像分割网络存在边缘分割不清晰、缺失值大等问题&#xff0c;该文提出一种具有边缘增强特点的医学图像分割网…

社交圈子小程序搭建-源码部署-服务公司

消息通知:当有新的消息、评论或回复时&#xff0c;用户需要收到系统的推送通知&#xff0c;以便及时查看和回复 活动发布与参加:用户可以在社交圈子中发布各种类型的活动&#xff0c;如聚餐、旅游、运动等。其他用户可以参加这些活动&#xff0c;并与组织者进行交流和沟通 社交…

C#初级——输出语句和转义字符

输出语句 在C#中&#xff0c;C#的输出语句是通过Console类进行输出&#xff0c;该类是一个在控制台下的一个标准输入流、输出流和错误流。使用该类下的Write()函数&#xff0c;即可打印要输出的内容。 Console.Write("Hello World!"); //在控制台应用中打印Hell…

通过QT进行服务器和客户端之间的网络通信

客户端 client.pro #------------------------------------------------- # # Project created by QtCreator 2024-07-02T14:11:20 # #-------------------------------------------------QT core gui network #网络通信greaterThan(QT_MAJOR_VERSION, 4): QT widg…

Docker安装nacos(详细教程)

Nacos 是一个开源的动态服务发现、配置管理和服务管理平台&#xff0c;广泛用于微服务架构中。在本文章中&#xff0c;博主将详细介绍如何使用 Docker 来安装 Nacos&#xff0c;以便快速启动并运行这个强大的服务管理工具。 前置条件 在开始安装 Nacos 之前&#xff0c;请确保…

解决union all之后字段返回非该字段类型的值

首先明确一个概念&#xff0c;union all的两部分的结果表的字段必须名称&#xff0c;类型&#xff0c;位置的先后都完全一样才可以 我的错误&#xff1a;一个datetime类型的字段&#xff0c;单独查询没问题&#xff0c;union all之后却返回了0 原因&#xff1a;字段顺序问题 …

DP(7) | 打家劫舍① | Java | LeetCode 198, 213, 337 做题总结

打家劫舍问题 来源于代码随想录&#xff1a;https://programmercarl.com/0198.%E6%89%93%E5%AE%B6%E5%8A%AB%E8%88%8D.html#%E6%80%9D%E8%B7%AF ① 确定dp数组&#xff08;dp table&#xff09;以及下标的含义 dp[i]&#xff1a;考虑下标i&#xff08;包括i&#xff09;以内的房…

pytorch 笔记:torch.optim.Adam

torch.optim.Adam 是一个实现 Adam 优化算法的类。Adam 是一个常用的梯度下降优化方法&#xff0c;特别适合处理大规模数据集和参数的深度学习模型 torch.optim.Adam(params, lr0.001, betas(0.9, 0.999), eps1e-08, weight_decay0, amsgradFalse, *, foreachNone, maximizeFa…

配置阿里云

ubuntu 20.04 设置国内镜像源&#xff08;阿里源、清华源&#xff09;_ubuntu 20.04 镜像源-CSDN博客 参考 sudo cp /etc/apt/sources.list /etc/apt/sources.list.back vim /etc/apt/sources.list sudo apt update sudo apt upgrade阿里云Ubuntu镜像&#xff1a;https://d…

I2C总线二级外设驱动开发(函数和代码详解)

I2C总线二级外设驱动开发是一个涉及多个步骤和函数调用的过程&#xff0c;主要目的是使得挂接在I2C总线上的外设能够正常工作。 一、I2C总线二级外设驱动开发概述 I2C总线是一种广泛使用的串行通信总线&#xff0c;用于连接微控制器及其外围设备。在Linux内核中&#xff0c;I2…

实验四 FPGA 使用Verilog HDL设计电机运动控制程序

实验目的 1.掌握使用GPIO控制直流电机的原理。 2.掌握使用Verilog HDL设计电机运动控制程序的方法。 实验要求 采用Verilog HDL语言设计直流电机运动控制程序&#xff0c;实现直流电机的运动控制&#xff0c;并通过数码管显示当前输出的PWM波的占空比。通过按键或拔位开关可…

ArcGIS Pro不能编辑ArcGIS10.X的注记的解决办法

​ 点击下方全系列课程学习 点击学习—>ArcGIS全系列实战视频教程——9个单一课程组合系列直播回放 点击学习——>遥感影像综合处理4大遥感软件ArcGISENVIErdaseCognition 一、问题 我们利用ArcGIS Pro编辑ArcGIS10.X系列软件生成的注记要素类的时候&#xff0c;会提示不…

Apache POI-Excel入门与实战

目录 一、了解Apache POI 1.1 什么是Apache POI 1.2 为什么要使用ApaChe POI 1.3 Apache POI应用场景 1.4 Apache POI 依赖 二、Apache POI-Excel 入门案例 2.1 写入Excel文件 2.2 读取文件 四、Apache POI实战 4.1 创建一个获取天气的API 4.2高德天气请求API与响应…

iphone11 如何打开开发者模式?

嗨&#xff0c;大家好&#xff0c;我是兰若姐姐。 今天有小伙伴在问&#xff0c;怎么打开ios手机的开发者模式&#xff0c;他需要做app自动化测试&#xff0c;他的手机是是iphone11&#xff0c;今天就把iphone11开发者打开的步骤给记录分享下 在电脑上安装 Xcode&#xff1a;开…

Sqlmap中文使用手册 - Techniques模块参数使用

目录 1. Techniques模块的帮助文档2. 各个参数的介绍2.1 --techniqueTECH2.2 --time-secTIMESEC2.3 --union-colsUCOLS2.4 --union-charUCHAR2.5 --union-fromUFROM2.6 --dns-domainDNS2.7 --second-urlSEC2.8 --second-reqSEC 1. Techniques模块的帮助文档 Techniques:These o…

怎样使用 Juicer tools 的 dump 命令将.hic文件转换为交互矩阵matrix计数文件 (Windows)

创作日志&#xff1a; 万恶的生信…一个scHiC数据集没有提供处理好的计数文件&#xff0c;需要从.hic转换。Github一个个好长的文档看了好久才定位到 juicer tools 的dump命令&#xff0c;使用起来比想象中简单。 一、下载Juicer tools 注意&#xff1a;使用Juicer tools的前提…

邮件安全篇:邮件反垃圾系统运作机制简介

1. 什么是邮件反垃圾系统&#xff1f; 邮件反垃圾系统是一种专门设计用于检测、过滤和阻止垃圾邮件的技术解决方案。用于保护用户的邮箱免受未经请求的商业广告、诈骗信息、恶意软件、钓鱼攻击和其他非用户意愿接收的电子邮件的侵扰。 反垃圾系统的常见部署形式 2. 邮件反垃圾…

Dubbo SPI 之路由器

1. 背景介绍 Dubbo 是一个高性能的 Java RPC 框架&#xff0c;由阿里巴巴开源并广泛应用于分布式系统中。在 Dubbo 的架构中&#xff0c;SPI&#xff08;Service Provider Interface&#xff09;是一个关键组件&#xff0c;允许在运行时动态加载不同的服务实现。SPI 机制提供了…

day6 io线程

获取终端输入的字符