Python底层技术揭秘:如何实现图算法
时间:2023-11-08 14:19:17 109浏览 收藏
欢迎各位小伙伴来到golang学习网,相聚于此都是缘哈哈哈!今天我给大家带来《Python底层技术揭秘:如何实现图算法》,这篇文章主要讲到等等知识,如果你对文章相关的知识非常感兴趣或者正在自学,都可以关注我,我会持续更新相关文章!当然,有什么建议也欢迎在评论留言提出!一起学习!
随着计算机技术的不断发展,图论(graph theory)及其相关算法已经成为了计算机领域中非常重要的一部分。而对于Python程序员来说,掌握这些底层技术不仅可以提高代码的效率和质量,还有助于优化程序的性能和开发效率。
本文将介绍Python实现图算法的底层技术,包括图的存储方式、遍历方式、最短路径算法、最小生成树算法以及拓扑排序算法,重点介绍各算法的实现思路和代码示例。
一、图的存储方式
在Python中,我们可以使用邻接矩阵或邻接表来存储图。
1、邻接矩阵
邻接矩阵是一个二维矩阵,其中顶点的行和列分别对应两个顶点。如果两个顶点之间有边相连,则该位置值设为1或其边权值;否则设为0。例如,下面是一个邻接矩阵的例子:
graph = [[0, 1, 1, 0], [1, 0, 1, 1], [1, 1, 0, 1], [0, 1, 1, 0]]
这个矩阵表示一个无向图,共有4个顶点,其中1、2、3之间互相有连边。
2、邻接表
邻接表是一个字典,其中每个键对应一个顶点,对应的值是该顶点的邻居顶点列表。例如:
graph = {0: [1, 2], 1: [0, 2, 3], 2: [0, 1, 3], 3: [1, 2]}
这个字典表示同样的无向图,其中每个键值对应一个顶点,这个顶点对应的值是这个顶点和其它顶点之间的连边。
二、图的遍历方式
1、深度优先遍历(DFS)
深度优先遍历是搜索所有子树的深度方向,也就是先访问当前顶点,然后递归访问它的每一个邻居顶点。对于每个顶点,我们必须记住它是否被访问过;如果未访问,就递归遍历它的邻居顶点。代码实现:
def dfs(graph, start, visited=None): if visited is None: visited = set() visited.add(start) print(start) for next_vertex in graph[start] - visited: dfs(graph, next_vertex, visited) return visited
2、广度优先遍历(BFS)
广度优先遍历是搜索所有子树的广度方向,也就是先访问当前顶点,然后访问它的所有邻居顶点。对于每个顶点,我们必须记住它是否被访问过;如果未访问,就加入队列中并标记为已访问,然后递归它的邻居顶点。代码实现:
from collections import deque def bfs(graph, start): visited, queue = set(), deque([start]) visited.add(start) while queue: vertex = queue.popleft() print(vertex) for next_vertex in graph[vertex] - visited: visited.add(next_vertex) queue.append(next_vertex)
三、图算法
1、最短路径算法
最短路径算法是寻找图中两个顶点之间最短路径的算法。其中,Dijkstra算法用于有向无环图(DAG),Bellman-Ford算法适用于任何图。
(1)Dijkstra算法
Dijkstra算法用于有向无环图,并且只能处理非负权值的图。该算法的核心是贪心策略,即假定路径是由许多独立的单元(节点)组成的,对每个单元的最短路径进行逐一考虑,找到全局最短路。代码实现:
import heapq import sys def dijkstra(graph, start): visited = set() distance = {vertex: sys.maxsize for vertex in graph} distance[start] = 0 queue = [(0, start)] while queue: dist, vertex = heapq.heappop(queue) if vertex not in visited: visited.add(vertex) for neighbor, weight in graph[vertex].items(): total_distance = dist + weight if total_distance < distance[neighbor]: distance[neighbor] = total_distance heapq.heappush(queue, (total_distance, neighbor)) return distance
(2)Bellman-Ford算法
Bellman-Ford算法能够处理任何图,包括负权值的图。该算法通过动态规划的方式来解决最短路径问题。代码实现:
import sys def bellman_ford(graph, start): distance = {vertex: sys.maxsize for vertex in graph} distance[start] = 0 for _ in range(len(graph) - 1): for vertex in graph: for neighbor, weight in graph[vertex].items(): total_distance = distance[vertex] + weight if total_distance < distance[neighbor]: distance[neighbor] = total_distance return distance
2、最小生成树算法
最小生成树问题是寻找无向加权图的所有顶点所构成的子图,使得该子图中所有边的权值之和最小。其中,Kruskal和Prim算法都是解决该问题的经典算法。
(1)Kruskal算法
Kruskal算法是一种贪心算法,从所有边中选取权值最小的边,依次寻找下一条权值最小的边,直到顶点数与边数匹配为止。代码实现:
def kruskal(graph): parent = {} rank = {} for vertex in graph: parent[vertex] = vertex rank[vertex] = 0 minimum_spanning_tree = set() edges = list(graph.edges) edges.sort() for edge in edges: weight, vertex1, vertex2 = edge root1 = find(parent, vertex1) root2 = find(parent, vertex2) if root1 != root2: minimum_spanning_tree.add(edge) if rank[root1] > rank[root2]: parent[root2] = root1 else: parent[root1] = root2 if rank[root1] == rank[root2]: rank[root2] += 1 return minimum_spanning_tree
(2)Prim算法
Prim算法开始任选一个顶点作为起点,每次根据当前生成树与图中其它顶点的距离,以及其它顶点与当前生成树的最小距离来选择一个新的顶点加入到生成树中。代码实现:
import heapq def prim(graph, start): minimum_spanning_tree = set() visited = set(start) edges = list(graph[start].items()) heapq.heapify(edges) while edges: weight, vertex1 = heapq.heappop(edges) if vertex1 not in visited: visited.add(vertex1) minimum_spanning_tree.add((weight, start, vertex1)) for vertex2, weight in graph[vertex1].items(): if vertex2 not in visited: heapq.heappush(edges, (weight, vertex1, vertex2)) return minimum_spanning_tree
3、拓扑排序算法
拓扑排序算法主要用于处理有向无环图中的逻辑依赖关系,通常用来解决编译依赖或任务调度问题。代码实现:
from collections import defaultdict def topological_sort(graph): in_degree = defaultdict(int) for vertex1 in graph: for vertex2 in graph[vertex1]: in_degree[vertex2] += 1 queue = [vertex for vertex in graph if in_degree[vertex] == 0] result = [] while queue: vertex = queue.pop() result.append(vertex) for next_vertex in graph[vertex]: in_degree[next_vertex] -= 1 if in_degree[next_vertex] == 0: queue.append(next_vertex) if len(result) != len(graph): raise ValueError("The graph contains a cycle") return result
四、总结
本文介绍了Python实现图算法的底层技术,包括图的存储方式、遍历方式、最短路径算法、最小生成树算法以及拓扑排序算法,通过具体的代码示例,让读者了解每种算法的实现思路和代码实现细节。在实际开发过程中,读者可以根据自己的需求选择不同的算法,以提高程序的效率和质量。
到这里,我们也就讲完了《Python底层技术揭秘:如何实现图算法》的内容了。个人认为,基础知识的学习和巩固,是为了更好的将其运用到项目中,欢迎关注golang学习网公众号,带你了解更多关于Python,图算法,底层技术的知识点!
-
501 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
110 收藏
-
281 收藏
-
238 收藏
-
430 收藏
-
209 收藏
-
447 收藏
-
457 收藏
-
102 收藏
-
501 收藏
-
207 收藏
-
398 收藏
-
367 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 542次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 508次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 497次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 484次学习