Python 中的 Dijkstra 算法(查找最短路径)

2023-10-12

Dijkstra算法的工作原理是通过迭代找到节点的最短距离值,直到达到实际的最短距离。

Dijkstra 算法的一个关键方面是它使用优先队列从尚未处理的节点集中选择具有最小暂定距离的顶点。

当前节点被标记为已访问,并检查其所有邻居节点是否有更优化的路径。

Python 中的 Dijkstra 算法实际效果如下:


# Sample Graph represented as a dictionary
graph = {
  'A': {'B': 1, 'C': 4},
  'B': {'A': 9, 'D': 2},
  'C': {'A': 4, 'D': 6, 'F': 3},
  'D': {'B': 1, 'C': 1, 'E': 8},
  'E': {'D': 3},
  'F': {'C': 2}
}

def dijkstra(graph, start_node):
    pass  # algorithm implementation comes later  

The dijkstra函数是算法的主要实现,以图和起始节点作为参数。

 

 

理解图论

在我们深入研究 Dijkstra 算法之前,了解图论的基本原理至关重要。

图是一种对不同对象之间的关系进行建模的数学结构。在我们的教程中,这些对象是nodes在图表中。

这些节点之间的连接称为edges。这些边和节点的性质定义了图的类型,例如有向图、无向图、加权图和无权图。

对于 Dijkstra 的最短路径算法,我们通常使用加权图和有向图,但该算法也适用于未加权图和无向图。

创建图表的 Python 代码很简单。例如:


# Sample Graph represented as a dictionary
graph = {
  'A': {'B': 1, 'C': 4},
  'B': {'A': 9, 'D': 2},
  'C': {'A': 4, 'D': 6, 'F': 3},
  'D': {'B': 1, 'C': 1, 'E': 8},
  'E': {'D': 3},
  'F': {'C': 2}
}  

这是图的基本表示,其中“A”、“B”、“C”、“D”、“E”和“F”是图中的节点,数字是节点之间的边的权重。

 

图的组成部分:节点和边

图由两个关键组件组成:节点和边。节点,也称为顶点,是形成图的基本单位。

它们可以代表各种现实世界的实体,例如地图上的城市或互联网上的网页。

另一方面,边是连接这些节点的线。它们可以是有向的(单向)或无向的(双向)。

在加权图中,边还带有一个称为“weight',通常表示两个节点之间的距离或成本。

为了在 Python 中表示这些组件,我们经常使用列表、字典或两者的组合等数据结构。让我们看一个代码示例:


# Defining nodes and edges
nodes = ["A", "B", "C", "D", "E", "F"]
edges = [("A", "B", 1), ("A", "C", 4), ("B", "D", 2), ("C", "D", 6), ("C", "F", 3), ("D", "E", 8), ("E", "D", 3), ("F", "C", 2)]

# Converting to a graph representation
graph = {node: {} for node in nodes}
for edge in edges:
    graph[edge[0]][edge[1]] = edge[2]

print(graph)  

Output:


{
  'A': {'B': 1, 'C': 4},
  'B': {'D': 2},
  'C': {'D': 6, 'F': 3},
  'D': {'E': 8},
  'E': {'D': 3},
  'F': {'C': 2}
}  

该代码首先定义节点和边。然后它将这些信息转换为基于字典的图形表示。

在这个字典中,每个键值对分别对应一个节点及其相邻的顶点。

邻接列表被表示为另一个字典,其中每个键值对分别对应于相邻节点和连接节点对的边的权重。

算法的逐步解释

以下是 Dijkstra 算法工作原理的概述:

  1. 初始化一个字典,该字典将存储从源到所有其他顶点的最短距离。
  2. 创建一个优先级队列来保存距离最小的顶点。
  3. 将源到源本身的距离设置为 0。
  4. 对于当前节点,考虑其所有未访问过的邻居节点,并计算它们经过当前节点的暂定距离。
  5. 将新计算出的暂定距离与当前分配的值进行比较,并分配较小的值。
  6. 将当前节点移动到访问集中;我们已经考虑完了。
  7. 继续这个过程,直到访问完所有顶点。

import heapq
def dijkstra(graph, source):
    distance = {node: float('infinity') for node in graph}
    distance[source] = 0
    queue = [(0, source)]
    while queue:
        current_distance, current_node = heapq.heappop(queue)

        if current_distance > distance[current_node]:
            continue

        for neighbor, weight in graph[current_node].items():
            distance_through_current_node = current_distance + weight

            if distance_through_current_node < distance[neighbor]:
                distance[neighbor] = distance_through_current_node
                heapq.heappush(queue, (distance[neighbor], neighbor))

    return distance
print(dijkstra(graph, 'A'))  

Output:


{'A': 0, 'B': 1, 'C': 4, 'D': 3, 'E': 11, 'F': 7}  

在此代码中,我们将源节点到所有其他节点的距离初始化为infinity,除了源节点本身,它是 0。然后我们开始从源节点开始迭代图。

while 循环一直运行,直到队列中有节点为止。在每次迭代中,我们从一开始就选择一个具有最小权重路径的节点,并考虑其所有未访问的邻居。

如果计算出的通过当前节点的距离小于先前已知的距离,我们会更新该邻居的最短距离。

一旦访问了所有节点,我们就返回从源到所有其他顶点的最短距离。输出是一个字典,其中包含图中的每个节点以及距源节点的最短距离。

 

处理边缘情况和潜在错误

在实现 Dijkstra 算法时,您应该注意某些边缘情况和潜在错误。让我们讨论一些以及如何处理它们:

  1. 空图:没有节点或边的空图会导致错误,因为没有路径可供查找。我们应该在运行算法之前检查图是否为空。
  2. 无效的源节点:如果源节点不存在于图中,则算法将失败。我们需要检查图中是否存在源节点。
  3. 断开连接图:如果图中有两个或多个断开的组件,Dijkstra 算法将无法找到位于不同组件的节点之间的路径。这并不完全是一个错误,而是算法的固有限制。该算法仍将正常执行,但结果可能不是您所期望的。
  4. 负边权重:Dijkstra 算法不处理负边权重。如果您的图表包含负权重,您可能需要使用贝尔曼-福特或约翰逊算法。

我们来处理这些情况:


def dijkstra(graph, source):
    # Check if the graph is empty
    if not graph:
        return "Error: Graph is empty"

    # Check if the source node is valid
    if source not in graph:
        return "Error: Invalid source node"

    distance = {node: float('infinity') for node in graph}
    distance[source] = 0
    queue = [(0, source)]

    while queue:
        current_distance, current_node = heapq.heappop(queue)
        if current_distance > distance[current_node]:
            continue

        for neighbor, weight in graph[current_node].items():
            # Check for negative edge weights
            if weight < 0:
                return "Error: Graph contains negative edge weights"

            distance_through_current_node = current_distance + weight
            if distance_through_current_node < distance[neighbor]:
                distance[neighbor] = distance_through_current_node
                heapq.heappush(queue, (distance[neighbor], neighbor))
    return distance
print(dijkstra(graph, 'A'))  

输出和解释将与上一节相同,但现在该函数更加健壮,可以处理一些边缘情况和错误。

 

可视化 Dijkstra 算法

可视化像 Dijkstra 算法这样的算法可以极大地帮助理解它如何运行并迭代图表以找到最短路径。

我们可以使用 Python 中的 matplotlib 和 networkx 库来完成此操作。


import networkx as nx
import matplotlib.pyplot as plt
G = nx.DiGraph()  # Create a new directed graph G

# Add edges with weights (replicating our example graph)
G.add_edge('A', 'B', weight=1)
G.add_edge('A', 'C', weight=4)
G.add_edge('B', 'D', weight=2)
G.add_edge('C', 'D', weight=6)
G.add_edge('C', 'F', weight=3)
G.add_edge('D', 'E', weight=8)

# Specify the positions of each node
pos = {'A': (0, 0), 'B': (1, 1), 'C': (1, -1), 'D': (2, 0), 'E': (3, 0), 'F': (2, -1)}

# Create edge labels for the weights
labels = nx.get_edge_attributes(G, 'weight')

# Draw the nodes
nx.draw_networkx_nodes(G, pos, node_color='orange')

# Draw the edges
nx.draw_networkx_edges(G, pos)

# Draw the node labels
nx.draw_networkx_labels(G, pos)

# Draw the edge labels
nx.draw_networkx_edge_labels(G, pos, edge_labels=labels)

plt.show()  # Display the graph  

Output:

在这段代码中,我们使用networkx创建一个图,添加带有权重的边,并指定每个节点的位置。然后,我们绘制节点、边、节点标签和边标签(权重)。

最终结果是一个可视化图表,它让我们清楚地了解 Dijkstra 算法如何在图表中导航以找到最短路径。

 

从两个起点寻找最优路线

在某些情况下,您可能想要确定从两个起点到目的地的最短路径。

起始节点将是start_node1‘A’和start_node2‘B’,目标节点是end_node ‘E’.


import heapq
def dijkstra(graph, start_node):
    distance = {node: float('inf') for node in graph}
    predecessor = {node: None for node in graph}
    distance[start_node] = 0
    queue = [(0, start_node)]
    while queue:
        current_distance, current_node = heapq.heappop(queue)

        for neighbor, weight in graph[current_node].items():
            new_distance = current_distance + weight
            if new_distance < distance[neighbor]:
                distance[neighbor] = new_distance
                predecessor[neighbor] = current_node
                heapq.heappush(queue, (new_distance, neighbor))
    return distance, predecessor

def find_shortest_path(graph, start_node1, start_node2, end_node):
    distance_from_start1, predecessor_from_start1 = dijkstra(graph, start_node1)
    distance_from_start2, predecessor_from_start2 = dijkstra(graph, start_node2)
    shortest_distance = min(
        distance_from_start1[end_node],
        distance_from_start2[end_node]
    )
    if shortest_distance == float('inf'):
        return None  # No path found
    path = [end_node]
    if distance_from_start1[end_node] <= distance_from_start2[end_node]:
        while path[-1] != start_node1:
            path.append(predecessor_from_start1[path[-1]])
    else:
        while path[-1] != start_node2:
            path.append(predecessor_from_start2[path[-1]])
    return path[::-1]
graph = {
    'A': {'B': 1, 'C': 4},
    'B': {'A': 9, 'D': 2},
    'C': {'A': 4, 'D': 6, 'F': 3},
    'D': {'B': 1, 'C': 1, 'E': 8},
    'E': {'D': 3},
    'F': {'C': 2}
}
start_node1 = 'A'
start_node2 = 'B'
end_node = 'E'

shortest_path = find_shortest_path(graph, start_node1, start_node2, end_node)
if shortest_path:
    print(f"Shortest path from either {start_node1} or {start_node2} to {end_node}: {' -> '.join(shortest_path)}")
else:
    print(f"No path found from either {start_node1} or {start_node2} to {end_node}")
  

Output:


Shortest path from either A or B to E: B -> D -> E  

功能find_shortest_path(graph, start_node1, start_node2, end_node)计算两者的最短路径start_node1 and start_node2 to end_node.

它使用了上面的dijkstra函数获取两个起始节点的距离和前驱字典。

到最短距离end_node然后确定从任一起始节点开始。

使用适当的前驱字典,该函数从结束节点回溯到所选的起始节点以构造路径。

我们可以使用 matplotlib 可视化该图,以便更好地理解:

如您所见,最短路径是 B -> D -> E。

突出显示最短路径

您可以使用networkx and matplotlib以编程方式可视化并突出显示路径:


import networkx as nx
import matplotlib.pyplot as plt
def visualize_graph_with_highlighted_path(graph, shortest_path):
    G = nx.DiGraph()
    for node, neighbors in graph.items():
        for neighbor, weight in neighbors.items():
            G.add_edge(node, neighbor, weight=weight)

    pos = nx.spring_layout(G)
    nx.draw(G, pos, with_labels=True, node_size=800, node_color='lightgray', font_size=15)

    # If there's a shortest path, highlight it
    if shortest_path:
        path_edges = [(shortest_path[i], shortest_path[i+1]) for i in range(len(shortest_path)-1)]
        nx.draw_networkx_nodes(G, pos, nodelist=shortest_path, node_color='yellow', node_size=800)
        nx.draw_networkx_edges(G, pos, edgelist=path_edges, edge_color='blue', width=2.5, arrowstyle='-|>')
    plt.show()
visualize_graph_with_highlighted_path(graph, shortest_path)
  

作为最短路径一部分的节点以黄色突出显示。

形成最短路径的边缘以蓝色显示,并带有较宽的线条和箭头。

 

时间复杂度分析

Dijkstra 算法的时间复杂度取决于用于图的数据结构以及根据未访问节点与源的暂定距离对未访问节点进行排序的数据结构。

当使用图的邻接矩阵表示时,时间复杂度为 O(V^2),其中 V 是顶点数。

这是因为我们需要扫描所有节点以选择具有最小距离值的节点。这种方法适用于处理边数接近 V^2 的密集图。

然而,对于稀疏图(其中边的数量远小于 V^2),更有效的方法是使用图的邻接表和优先级队列来提取具有最小距离的节点。能够将 Dijkstra 算法的时间复杂度降低到 O((V+E)logV) 的最合适的数据结构是二叉堆。

在我们的 Python 实现中,我们使用了heapq模块,它实现了二叉堆,从而使算法更加高效。

 

空间复杂度分析

Python 中 Dijkstra 算法的空间复杂度取决于图的表示,特别是我们如何存储节点和边。

如果我们使用邻接矩阵来表示图,则空间复杂度将为 O(V^2),其中 V 是顶点数。

这是因为我们需要存储矩阵中每个节点的所有边,无论两个节点之间是否存在边。

如果我们使用邻接表,空间复杂度将为 O(V + E),其中 E 是边的数量。对于 E 远小于 V^2 的稀疏图,这是一种更有效的方法。

在邻接表表示中,每个节点直接保存其邻居,从而节省空间。

在我们的Python实现中,我们使用字典来实现邻接表,并且我们还保留距离字典和队列。因此,我们实现的空间复杂度是 O(V + E)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Python 中的 Dijkstra 算法(查找最短路径) 的相关文章

  • 如何在 Windows 64 上安装 NumPy?

    NumPy 安装程序在注册表中找不到 python 路径 无法安装 需要 Python 2 5 版本 但在注册表中未找到该版本 OK 我必须修改注册表吗 我已经修改了 PATH 以指向Python25安装目录 我可以检查一下您使用的是什么安
  • Twisted 的 Deferred 和 JavaScript 中的 Promise 一样吗?

    我开始在一个需要异步编程的项目中使用 Twisted 并且文档非常好 所以我的问题是 Twisted 中的 Deferred 与 Javascript 中的 Promise 相同吗 如果不是 有什么区别 你的问题的答案是Yes and No
  • Sublime Text 插件开发中的全局 Python 包

    一 总结 我不知道 Sublime Text 插件开发人员如何使用 Sublime Text 查找全局 Python 包 而不是 Sublime Text 目录的 Python 包 Sublime Text使用自己的Python环境 而不是
  • 使用 python 中的公式函数使从 Excel 中提取的值的百分比相等

    import xlrd numpy excel Users Bob Desktop wb1 xlrd open workbook excel assignment3 xlsx sh1 wb1 sheet by index 0 colA co
  • 为什么删除临时文件时出现WindowsError?

    我创建了一个临时文件 向创建的文件添加了一些数据 已保存 然后尝试将其删除 但我越来越WindowsError 编辑后我已关闭该文件 如何检查哪个其他进程正在访问该文件 C Documents and Settings Administra
  • Pandas:GroupBy 到 DataFrame

    参考这个关于 groupby 到 dataframe 的非常流行的问题 https stackoverflow com questions 10373660 converting a pandas groupby object to dat
  • 如何检查python xlrd库中的excel文件是否有效

    有什么办法与xlrd库来检查您使用的文件是否是有效的 Excel 文件 我知道还有其他库可以检查文件头 我可以使用文件扩展名检查 但为了多平台性我想知道是否有任何我可以使用的功能xlrd库本身在尝试打开文件时可能会返回类似 false 的内
  • 工作日重新订购 Pandas 系列

    使用 Pandas 我提取了一个 CSV 文件 然后创建了一系列数据来找出一周中哪几天崩溃最多 crashes by day bc DAY OF WEEK value counts 然后我将其绘制出来 但当然它按照与该系列相同的排名顺序绘制
  • sklearn 中的 pca.inverse_transform

    将我的数据拟合后 X 我的数据 pca PCA n components 1 pca fit X X pca pca fit transform X 现在 X pca 具有一维 当我根据定义执行逆变换时 它不是应该返回原始数据 即 X 二维
  • 一段时间后终止线程的最 Pythonic 方法

    我想在线程中运行一个进程 它正在迭代一个大型数据库表 当线程运行时 我只想让程序等待 如果该线程花费的时间超过 30 秒 我想终止该线程并执行其他操作 通过终止线程 我的意思是我希望它停止活动并优雅地释放资源 我认为最好的方法是通过Thre
  • 结构差异 sudo() run('sudo 命令')

    我想知道函数之间有什么区别sudo 和函数run sudo u user smth 文档上有 sudo 在所有运行方式上都是相同的 除了它总是换行 调用 sudo 程序中的给定命令以提供超级用户 特权 但有几次 sudo cmd 提示我输入
  • Django 的 request.FILES 出现 UnicodeDecodeError

    我在视图调用中有以下代码 def view request body u for filename f in request FILES items body body Filename filename n f read n 在某些情况下
  • pytest:同一接口的不同实现的可重用测试

    想象一下我已经实现了一个名为的实用程序 可能是一个类 Bar在一个模块中foo 并为其编写了以下测试 测试 foo py from foo import Bar as Implementation from pytest import ma
  • .pyx 文件出现未知文件类型错误

    我正在尝试构建一个包含 pyx 文件的 Python 包 pyregion 但在构建过程中出现错误 检查以下输出 python setup py build running build running build py creating b
  • 使用Python计算目录的大小?

    在我重新发明这个特殊的轮子之前 有没有人有一个很好的例程来使用 Python 计算目录的大小 如果例程能够很好地以 Mb Gb 等格式格式化大小 那就太好了 这会遍历所有子目录 总结文件大小 import os def get size s
  • 通过索引访问Python字典的元素

    考虑一个像这样的字典 mydict Apple American 16 Mexican 10 Chinese 5 Grapes Arabian 25 Indian 20 例如 我如何访问该字典的特定元素 例如 我想在对 Apple 的第一个
  • 使用 Pandas 计算 delta 列

    我有一个数据框 如下所示 Name Variable Field A 2 3 412 A 2 9 861 A 3 5 1703 B 3 5 1731 A 4 0 2609 B 4 0 2539 A 4 6 2821 B 4 6 2779 A
  • Mac OSX 10.6 上的 Python mysqldb 不工作

    我正在使用 Python 2 7 并尝试让 Django 项目在 MySQL 后端运行 我已经下载了 mysqldb 并按照此处的指南进行操作 http cd34 com blog programming python mysql pyth
  • Elasticsearch 通过搜索返回拼音标记

    我用语音分析插件 https www elastic co guide en elasticsearch plugins current analysis phonetic html由于语音转换 从弹性搜索中进行一些字符串匹配 我的问题是
  • 如何与其他用户一起使用 pyenv?

    如何与其他用户一起使用 pyenv 例如 如果我在用户 test 的环境中安装了 pyenv 则当我以 test 身份登录时可以使用 pyenv 但是 当我以其他用户 例如 root 身份登录时如何使用 pyenv 即使你这么做了 我也会s

随机推荐

  • 设置您的工作环境

    要下载本课程的数据集 您可以访问真正的 Python GitHub 存储库 有关本课程所涵盖概念的更多信息 您可以查看 Python 虚拟环境 入门 Visual Studio Code 中的 Python 开发 Jupyter Noteb
  • Python 中的字典

    目录 定义字典 访问字典值 字典键与列表索引 增量构建字典 字典键的限制 对字典值的限制 运算符和内置函数 Built in Dictionary Methods d clear d get d items d keys d values
  • 纯Python直方图

    当您准备绘制直方图时 最简单的方法是不要考虑箱 而是报告每个值出现的次数 频率表 一条蟒蛇字典非常适合这项任务 gt gt gt gt gt gt Need not be sorted necessarily gt gt gt a 0 1
  • 了解日期和时间是混乱的

    日期和时间并不是简单的事情 尤其是现在大多数计算都是远程完成的 无法保证计算机和用户位于同一个地方 由于管理夏令时和时区的规则不是静态的 这一事实使情况变得更加复杂 在本课程中 您将探索所有奇怪的边缘情况 并了解程序员通常如何处理它们
  • 掌握Python的内置时间模块

    蟒蛇time模块提供了多种方式代表时间代码中 例如对象 数字和字符串 它还提供除表示时间之外的功能 例如在代码执行期间等待和测量代码的效率 本课程将引导您了解最常用的函数和对象time 完成本课程后 您将能够 理解处理日期和时间的核心概念
  • 关于奥尔德伦·桑托斯

    关于奥尔德伦 桑托斯 个人网站 大家好 我是 Aldren Santos 担任自由平面设计师 插画师已有 3 年了 我的任务是尽我所能 让这个网站变得更加精彩 我真心希望我的插图能够吸引您通过我们团队辛勤工作的这些教程学习 Python 的
  • 编写和测试 Python 函数:面试练习(概述)

    无论您是想在编码面试中取得好成绩 还是只是想提高您的开发技能 解决编码挑战可以帮助您成长为一名程序员 在这个真实的 Python 代码对话中 Philipp 向 Martin 提出挑战 要求他编写一个函数 将字符串中的每个字符加倍 通过他们
  • 引导 Django 项目

    有关本课程所涵盖概念的更多信息 您可以查看 如何设置 Django 项目 真正的Python文章 使用 Django 和 Python 构建个人日记 真正的Python文章 以下是本课程中使用的命令行片段 mkdir portfolio p
  • Python 石头剪刀布:命令行游戏(概述)

    游戏编程是学习如何编程的好方法 您可以使用许多在现实世界中看到的工具 此外您还可以玩游戏来测试您的结果 开始 Python 游戏编程之旅的理想游戏是剪刀石头布 在本课程中 您将学习如何 自己编写代码剪刀石头布游戏 接受用户输入input 使
  • 2021 年 4 月 21 日

    主持人大卫 阿莫斯回答会员的问题 在这次会议上 我们讨论了 Real Python 的新功能 在哪里可以找到要阅读的代码以提高您的 Python 技能 为什么 0xfor x in 1 2 3 回报 15 数据科学 Django 和 Fla
  • Python 中的 K 均值聚类:实用指南

    目录 What Is Clustering 聚类技术概述 分区聚类 层次聚类 基于密度的聚类 How to Perform K Means Clustering in Python 了解 K 均值算法 使用 Python 编写您的第一个 K
  • 在 Python 中使用 lru_cache 进行缓存

    有很多方法可以实现快速响应的应用程序 缓存是一种方法 如果使用得当 可以使事情变得更快 同时减少计算资源的负载 蟒蛇的功能工具模块附带 lru cache 装饰器 这使您能够使用以下命令缓存函数的结果最近最少使用 LRU 策略 这是一种简单
  • 拼写错误、缺失或误用 Python 关键字

    以下是有关 Python 关键字的更多信息的资源 Python 关键字 简介 真正的 Python 文章 Python 3 8 关键字 Python 文档
  • Python 标准 REPL:快速尝试代码和想法

    目录 Getting to Know the Python Standard REPL 什么是 Python 的交互式 Shell 或 REPL 为什么使用 Python REPL Starting and Ending REPL Inte
  • 使用 Fabric 和 Ansible 自动化 Django 部署

    目录 设置和配置 Fabric Setup 设置 SSH 密钥 强化用户密码 安装 Ansible 依赖项 将 SELinux 设置为宽容模式 升级服务器 完整性检查 Ansible Primer 剧本 示例手册 Playbook Setu
  • 第 27 集:准备面试 Python 练习题

    第 27 集 准备面试 Python 练习题 真正的 Python 播客 2020 年 9 月 18 日47m RSS Apple Podcasts Google Podcasts Spotify More 播客瘾君子 灰蒙蒙 袖珍铸件 投
  • Python 基础知识:函数和循环(摘要)

    在本视频课程中 您了解了两个最基本的概念 在编程中 函数和循环 首先 您学习了如何定义自己的自定义函数 你看到了 该函数由两部分组成 这函数签名 这开始于def关键字并包括函数名称和函数参数 这函数体 其中包含每当调用该函数时运行的代码 函
  • Python 的 urllib.request 用于 HTTP 请求

    目录 使用 urllib request 的基本 HTTP GET 请求 The Nuts and Bolts of HTTP Messages 了解什么是 HTTP 消息 了解 urllib request 如何表示 HTTP 消息 关闭
  • Django Ninja 的隐蔽 REST API(摘要)

    在本课程中 您已经了解了 Django Ninja REST API 库的所有内容 使用 Ninja 您可以 使用装饰器快速包装 Django 视图创建 REST API 端点 使用类型注释定义变量和参数 写Schema和ModelSche
  • Python 中的 Dijkstra 算法(查找最短路径)

    Dijkstra算法的工作原理是通过迭代找到节点的最短距离值 直到达到实际的最短距离 Dijkstra 算法的一个关键方面是它使用优先队列从尚未处理的节点集中选择具有最小暂定距离的顶点 当前节点被标记为已访问 并检查其所有邻居节点是否有更优