【Python 算法】双向迪杰斯特拉算法 Python实现

双向迪杰斯特拉算法Python实现

文章目录

  • 双向迪杰斯特拉算法Python实现
    • 简介
    • 双向迪杰斯特拉算法优势
    • 局限性
    • 算法的基本步骤
      • 终止条件
    • 基本步骤
    • 伪代码
    • Python 实现

简介

双向迪杰斯特拉算法(Bi Directional Dijkstra Algorithm)是一种用于在加权图中查找两个顶点之间最短路径的算法,是Dijkstra算法的一个变种,基本思想是:从两个搜索方向同时开始搜索——从起点到终点方向和从终点到起点方向同时进行迪杰斯特拉算法搜索,如果存在路径,那么最终两个方向的搜索会在某点相遇并终止,而这条路径就是最短距离路径。在某些情况下,双向迪杰斯特拉算法可以减少搜索空间大小,从而提高算法效率。其中也有分治法的思想

双向迪杰斯特拉算法优势

与迪杰斯特拉算法相比,双向迪杰斯特拉算法在以下情况更有优势:

  1. 大规模图搜索:如果图的规模很大,双向迪杰斯特拉算法很可能会比迪杰斯特拉算法更快。

  2. 稀疏图:在稀疏图中,双向迪杰斯特拉算法很可能会比迪杰斯特拉算法更快。

最主要是因为双向搜索可以减少一定的搜索空间,从终点开始搜索和从起点开始搜索,相当于做了一次剪枝。

image-20231113185857959

(我觉得这张图很形象的解释了为什么双向迪杰斯特拉算法能够减少搜索空间,而单项迪杰斯特拉算法在大规模图中,会越来越发散)

局限性

  1. 复杂性:双向迪杰斯特拉算法需要更复杂的数据结构来跟踪记录两个方向的搜索路径。算法需要更多时间维护两个方向的队列。
  2. 权重不均等的图、负权重图:对于边权重差异比较大和负权重的图,双向迪杰斯特拉算法可能不会表现得很好。
  3. 当终点和起点距离比较近的时候,双向迪杰斯特拉算法算法可能不如单项迪杰斯特拉算法算法。

但是双向迪杰斯特拉还是具有减少搜索空间更快搜索到最短路径的优点。

算法的基本步骤

终止条件

双向迪杰斯特拉算法最重要的是,终止条件,算法在什么时候应该终止,如何确定相遇的点是应该终止算法的。双向迪杰斯特拉算法需要维护两个队列,一个是从起点到终点方向的队列queue_from_startqueue_from_target,设: t o p f top_f topfqueue_from_start优先级队列的队头元素, t o p r top_r toprqueue_from_target优先队列的队头元素, μ \mu μ用来记录相遇点构成的路径值,初始化 μ = ∞ \mu = \infty μ=。在进行路径搜索的时候,当存在一条边 ( u , v ) (u,v) (u,v)满足 u u u在前向搜索中,而 v v v在反向搜索中,如果 d f ( u ) + c ( u , v ) + d r ( v ) < μ d_f(u)+c(u,v)+d_r(v) < \mu df(u)+c(u,v)+dr(v)<μ,则更新 μ \mu μ值。

终止条件: t o p f + t o p r ≥ μ top_f + top_r \ge \mu topf+toprμ

双向迪杰斯特拉算法

基本步骤

  1. 初始化:将起点加入到正向搜索的待处理队列中,将终点加入到反向搜索的待处理队列中。
  2. 迭代搜索:在每一次迭代中,算法分别对正向和反向的待处理队列中的顶点进行处理,选择当前距离最小的顶点进行扩展。
  3. 扩展顶点:对于选中的顶点,算法更新其邻接顶点的最短路径估计,并将这些邻接顶点加入到相应的待处理集合中。
  4. 检查相遇:在每次扩展后,算法检查正向和反向的搜索是否在某个顶点上相遇。相遇的条件通常是检查某个顶点是否同时出现在正向和反向的访问表中。
  5. 路径重构:一旦搜索相遇,算法使用正向和反向的路径信息来重构出从起点到终点的最短路径。
  6. 终止条件:如果两个搜索在中间某处相遇,或者一个方向的搜索已经找不到新的顶点进行扩展,算法终止。

伪代码

程序结构:

function BidirectionalDijkstra(graph, start, end)
    create priority queues queueFromStart, queueFromEnd
    add start to queueFromStart with priority 0
    add end to queueFromEnd with priority 0
    create distance maps distanceFromStart, distanceFromEnd and set all distances to infinity
    set distanceFromStart[start] to 0
    set distanceFromEnd[end] to 0
    create parent maps parentFromStart, parentFromEnd and set all parents to null
    set parentFromStart[start] to start
    set parentFromEnd[end] to end

    while queueFromStart and queueFromEnd are not empty
        nodeFromStart = extract minimum from queueFromStart
        for each neighbor of nodeFromStart
            if distance through nodeFromStart to neighbor is less than distanceFromStart[neighbor]
                update distanceFromStart[neighbor]
                update parentFromStart[neighbor]
                add neighbor to queueFromStart with priority distanceFromStart[neighbor]

        nodeFromEnd = extract minimum from queueFromEnd
        for each neighbor of nodeFromEnd
            if distance through nodeFromEnd to neighbor is less than distanceFromEnd[neighbor]
                update distanceFromEnd[neighbor]
                update parentFromEnd[neighbor]
                add neighbor to queueFromEnd with priority distanceFromEnd[neighbor]

        if any node v is in both queueFromStart and queueFromEnd
            path = shortest path from start to v according to parentFromStart
            path = path + reverse of shortest path from v to end according to parentFromEnd
            return path

    return no path
	


Python 实现

def bidirectional_dijkstra_b(graph, start, target, i):

    queue_from_start = []
    hq.heappush(queue_from_start, (0.0, start))
    distance_from_start = {node: float('infinity') for node in graph}
    distance_from_start[start] = 0.0
    parents_of_start = {start: None}

    queue_from_target = []
    hq.heappush(queue_from_target, (0.0, target))
    distance_from_target = {node: float('infinity') for node in graph}
    distance_from_target[target] = 0.0
    parents_of_target = {target: None}

    close_of_start = set()          # 访问禁闭表
    close_of_target = set()         # 访问禁闭表

    miu = math.inf
    global node
    node = None

    while queue_from_start and queue_from_target:

        if queue_from_start[0][0] + queue_from_target[0][0] >= miu:
            return reverse_traversal(node, parents_of_start, parents_of_target)

        cur_dist, cur_node = hq.heappop(queue_from_start)
        close_of_start.add(cur_node)
        for adjacent, weight in graph[cur_node].items():
            
            if adjacent in close_of_start:
                continue
            distance = cur_dist + weight["weight"]

            if distance < distance_from_start[adjacent]:
                distance_from_start[adjacent] = distance
                parents_of_start[adjacent] = cur_node
                hq.heappush(queue_from_start, (distance, adjacent))
                # 更新miu值
                if adjacent in close_of_target:
                    dist = distance + distance_from_target[adjacent]
                    if miu > dist:
                        miu = dist
                        node = adjacent
                        
        cur_dist, cur_node = hq.heappop(queue_from_target)

        close_of_target.add(cur_node)
        for adjacent, weight in graph[cur_node].items():
            if adjacent in close_of_target:
                continue
            distance = cur_dist + weight["weight"]
            if distance < distance_from_target[adjacent]:
                distance_from_target[adjacent] = distance
                parents_of_target[adjacent] = cur_node
                hq.heappush(queue_from_target, (distance, adjacent))

                if adjacent in close_of_start:
                    dist = distance + distance_from_start[adjacent]
                    if miu > dist:
                        miu = dist
                        node = adjacent
                       
    return []

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

红色旅游AR互动体验将景区推向更广泛的市场

AR技术的出现使得各展厅观众可以在虚拟和现实的层面进行互动&#xff0c;利用AR和VR技术&#xff0c;将展览地点扩展到特定的虚拟领域&#xff0c;实现了"无触觉"交互体验&#xff0c;增强现实技术和展馆的对接更加激发人们了解新事物的兴趣。 一、AR景区&#xff1a…

【03】Istio Gateway示例配置

3.1 开放kiali至集群外部 首先将istio-inressateway暴露集群外部; 在node02的ens33网卡上面有多余的ip地址&#xff0c;将该地址绑定在igressgateway的svc 上面。 kubectl edit svc istio-ingressgateway -n istio-system定义kiali的ingress gateway的资源配置清单 apiVersion:…

第十六章,反射与注解例题

package 例题; import java.lang.reflect.Constructor;class 例题1Demo {//变量String s;int i, i2, i3;private 例题1Demo() {//无参构造方法}protected 例题1Demo(String s, int i) {//有参构造方法this.s s;this.i i;}public 例题1Demo(String... strings) throws NumberF…

堆排序(小根堆模板)

输入一个长度为 n 的整数数列&#xff0c;从小到大输出前 m 小的数。 输入格式 第一行包含整数 n 和 m。 第二行包含 n 个整数&#xff0c;表示整数数列。 输出格式 共一行&#xff0c;包含 m 个整数&#xff0c;表示整数数列中前 m 小的数。 数据范围 1≤m≤n≤10^5&am…

Centos8上部署Zabbix5.0

1.关闭Selinux及防火墙&#xff0c;避免Web页面无法访问。 setenforce 0 vim /etc/selinux/config 修改“SELINUX”等号后的内容为disabled SELINUXdisabled\\关闭并关闭开机自启 systemctl stop firewalld systemctl disable firewalld 2.配置Centos8本地yum源。 mkdir /mn…

『MySQL快速上手』-⑦-内置函数

文章目录 1.日期函数1.1 获得年月日1.2 获得时分秒1.3 获得时间戳1.4 在日期的基础上加日期1.5 在日期的基础上减去时间1.6 计算两个日期之间相差多少天案例1案例22.字符串函数案例3.数学函数4.其他函数1.日期函数 1.1 获得年月日

基于Python美化图片亮度和噪点

支持添加噪点类型包括&#xff1a;添加高斯噪点、添加椒盐噪点、添加波动噪点、添加泊松噪点、添加周期性噪点、添加斑点噪点、添加相位噪点&#xff0c;还提供清除噪点的功能。 我们先看一下实测效果&#xff1a;&#xff08;test.jpg为原图&#xff0c;new.jpg为添加后的图片…

Rust结构体的定义和实例化

1.结构体特点 Rust的结构体跟元组类型比较类似,它们都包含多个相关的值。和元组一样&#xff0c;结构体的每一部分可以是不同类型。但不同于元组&#xff0c;结构体需要命名各部分数据以便能清楚的表明其值的意义。由于有了这些名字&#xff0c;结构体比元组更灵活&#xff1a…

浅谈二叉树

✏️✏️✏️今天给大家分享一下二叉树的基本概念以及性质、二叉树的自定义实现&#xff0c;二叉树的遍历等。 清风的CSDN博客 &#x1f61b;&#x1f61b;&#x1f61b;希望我的文章能对你有所帮助&#xff0c;有不足的地方还请各位看官多多指教&#xff0c;大家一起学习交流&…

【CUDA编程--编程模型简介算子开发流程】

官方文档&#xff1a;https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html 什么是CUDA CUDA全称&#xff08;Compute Unified Device Architecture&#xff09;统一计算架构&#xff0c;是NVIDIA推出的并行计算平台深度学习加速&#xff1a;对于神经网络&…

无线通信测量仪器-4945B/C 无线电通信综合测试仪

01 4945B/C 无线电通信综合测试仪 产品综述&#xff1a; 4945B/4945C无线电通信综合测试仪是多功能、便携式无线电综合测试类仪器&#xff0c;基于软件无线电架构&#xff0c;集成了跳频信号发生与分析、矢量信号发生与解调分析、模拟调制信号发生与解调分析、音频信号发生与…

C语言求数组中出现次数最多的元素

一、前言 遇到一个需求&#xff0c;需要求数组中出现次数最多的元素&#xff0c;查找了一些资料&#xff0c;结合自己的思路&#xff0c;编写了程序并验证。 只考虑元素为非负整数的数组&#xff0c;如果有出现次数相同的元素&#xff0c;则返回较小元素。 二、编程思路 以数…

python3+requests+unittest实战系列【二】

前言&#xff1a;上篇文章python3requestsunittest&#xff1a;接口自动化测试&#xff08;一&#xff09;已经介绍了基于unittest框架的实现接口自动化&#xff0c;但是也存在一些问题&#xff0c;比如最明显的测试数据和业务没有区分开&#xff0c;接口用例不便于管理等&…

AI主播“败走”双11,想用AI省成本的商家醒醒吧,程序员不必担心失业,发展空间依旧很大

目录 1 2 3 “AI人”并不算是新鲜事&#xff0c;随着AI的发展&#xff0c;AI主播也开始悄悄进入到直播间中。 持续无间断的直播、比人工费便宜等优势&#xff0c;让很多商家选择了AI主播。 AI主播到底好不好用&#xff1f;终于在今年“双11”现出了原形。 1 AI主播没火过半年…

Python常用插件之emoji表情插件的用法

目录 一、概述 二、安装 三、基本用法 四、高级用法 1、自定义emoji表情 2、使用表情符号列表 3、结合使用Emoji和输入文本 4、动态添加emoji表情 5、自定义Emoji的样式 总结 一、概述 在Python中&#xff0c;使用emoji表情已经成为了一种非常流行的趋势。许多开发者…

Linux Centos 根目录扩展分区(保级教程)

Centos 根目录扩展分区 1. 扩展背景2.列出磁盘信息3. 对磁盘进行分区4. 重启Linux5. 将PV加入卷组centos并分区6.查看分区结果 1. 扩展背景 虚拟机初始分配20G内存&#xff0c;扩容到80G。 2.列出磁盘信息 可以得知容量信息以及即将创建的PV路径&#xff08;通常为“/dev/s…

tcpdump抓包的字节数量与ethtool统计数据不同的原因

情况介绍 在进行RDMA抓包流量分析时&#xff0c;我使用ethtool工具统计了RDMA网卡的流量发送数据数量&#xff0c;然后使用tcpdump进行抓包。 经过分析发现&#xff0c;tcpdump得到的数据数量总是大于ethtool得到的数据数量&#xff0c;而且每个数据包会多出4个字节。 分析 …

代码随想录算法训练营|五十一天

最长递增子序列 300. 最长递增子序列 - 力扣&#xff08;LeetCode&#xff09; 递推公式&#xff1a; 有点像双指针的操作&#xff0c;例如{2,5,6,4,3}&#xff08;写不出来&#xff0c;画图&#xff09; public class Solution {public int LengthOfLIS(int[] nums) {if (n…

如何计算掩膜图中多个封闭图形的面积

import cv2def calMaskArea(image,idx):mask cv2.inRange(image, idx, idx)contours, hierarchy cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)for contour in contours:area cv2.contourArea(contour)print("图形的面积为", area) image是…

Git的GUI图形化工具ssh协议IDEA集成Git

一、GIT的GUI图形化工具 1、介绍 Git自带的GUI工具&#xff0c;主界面中各个按钮的意思基本与界面文字一致&#xff0c;与git的命令差别不大。在了解自己所做的操作情况下&#xff0c;各个功能点开看下就知道是怎么操作的。即使不了解&#xff0c;只要不做push操作&#xff0c…