算法——结合实例了解深度优先搜索(DFS)

一,深度优先搜索(DFS)详解

DFS是什么?

深度优先搜索(Depth-First Search,DFS)是一种用于遍历或搜索树、图的算法。其核心思想是尽可能深地探索分支,直到无法继续时回溯到上一个节点,尝试其他分支。DFS的实现通常基于递归或**栈(后进先出)**结构,适合解决路径存在性、状态可达性问题,但不保证找到最短路径。

与BFS的区别

  • BFS逐层展开,适合找最短路径。
  • DFS沿单一分支深入,可能更快找到解,但路径不一定最短。

DFS实现步骤

以递归实现为例,步骤如下:

  1. 终止条件:检查当前节点是否为目标(如到达终点)。
  2. 标记访问:将当前节点标记为已访问,避免重复处理。
  3. 递归探索:遍历当前节点的所有相邻节点,对未访问的节点递归调用DFS。

栈实现步骤

  1. 将起始节点压入栈。
  2. 循环执行以下操作直到栈空:
    • 弹出栈顶节点。
    • 若未访问,标记为已访问并处理。
    • 将该节点的未访问相邻节点压入栈。

注意事项

1. 剪枝优化

在深度优先搜索中,剪枝是一种非常重要的优化策略。它的核心思想是在搜索过程中,判断某些路径是否不可能到达终点,如果确定不可能,则提前终止对这条路径的搜索,从而减少不必要的计算量,提高搜索效率 。以走迷宫为例,假设我们在迷宫中搜索从起点到终点的路径,当我们走到某个位置时,通过计算发现从这个位置无论怎么走,剩余的步数都无法到达终点(比如剩余的步数小于从当前位置到终点的曼哈顿距离),那么就可以直接放弃对这个位置后续路径的搜索 ,这就是一种简单的剪枝操作。再比如,在一个复杂的迷宫中,如果我们已经走过了一条很长的死胡同,那么当再次遇到类似的路径开头时,就可以直接判断这条路径很可能也是死胡同,从而提前剪枝 。剪枝可以大大减少搜索的空间和时间复杂度,尤其是在处理大规模问题时,效果更为显著 。

2. 避免重复访问

在 DFS 中,标记已访问节点是至关重要的。如果不标记已访问节点,当搜索到一个节点时,可能会不断地重复访问它,从而陷入死循环 。比如在一个图结构中,如果存在环,不标记已访问节点就会导致在环上无限循环 。为了避免这种情况,我们通常使用一个数组或集合来记录节点的访问状态 。在走迷宫的例子中,我们使用二维布尔数组visited来记录每个位置是否被访问过 ,当访问一个新位置时,首先检查visited数组中对应位置的值,如果为true,则说明该位置已经被访问过,不再进行处理;如果为false,则将其标记为true,并继续进行搜索 。在处理图的 DFS 时,也可以使用一个哈希集合来记录已访问的节点,这样可以快速判断一个节点是否已经被访问过 。避免重复访问不仅可以防止死循环,还可以提高搜索效率,因为不需要对已经访问过的节点进行重复处理 。

3. 边界条件处理

在实现 DFS 时,仔细考虑边界条件是确保程序正确性和稳定性的关键 。边界条件包括节点超出范围、数组越界等情况 。以走迷宫为例,在判断一个位置是否可以访问时,需要检查该位置的坐标是否在迷宫的范围内 。如果迷宫是一个n * m的二维数组,那么位置(x, y)必须满足0 <= x < n且0 <= y < m,否则就超出了边界 。在马走日的例子中,当计算马的下一步位置时,同样要检查新位置是否在棋盘内 。如果不处理这些边界条件,程序可能会访问到非法的内存位置,导致运行时错误,如数组越界异常等 。因此,在编写 DFS 代码时,一定要在递归调用之前,仔细检查边界条件,确保程序的健壮性 。


二,实例解析

实例1:中国象棋中马的日字形移动

在这里插入图片描述

问题描述
马从起点 (x, y) 出发,按“日”字形移动(横向±1且纵向±2,或横向±2且纵向±1),判断能否到达目标点 (tx, ty),并统计路径数。

DFS实现步骤

  1. 定义方向:8种可能的移动方向:
    directions = [ (2,1), (1,2), (-1,2), (-2,1),
                   (-2,-1), (-1,-2), (1,-2), (2,-1) ]
    
  2. 递归终止条件:当前位置等于目标位置时返回成功。
  3. 遍历所有方向:对每个方向计算新位置 (nx, ny),检查是否在棋盘内且未访问。
  4. 回溯恢复状态:递归返回后,将当前位置标记为未访问,以允许其他路径经过。

示例代码(伪代码)

def dfs(x, y, visited, target):
    if (x, y) == target:
        return 1  # 找到一条路径
    count = 0
    visited[x][y] = True
    for dx, dy in directions:
        nx, ny = x + dx, y + dy
        if 0 <= nx < 8 and 0 <= ny < 8 and not visited[nx][ny]:
            count += dfs(nx, ny, visited, target)
    visited[x][y] = False  # 回溯
    return count

实例2:走迷宫

在这里插入图片描述

问题描述
从迷宫起点 (0, 0) 出发,寻找一条到达终点 (m-1, n-1) 的路径。迷宫用二维数组 grid 表示,0 为通路,1 为墙。

DFS实现步骤

  1. 定义方向:上下左右四个移动方向。
    directions = [ (-1,0), (1,0), (0,-1), (0,1) ]
    
  2. 递归终止条件:当前位置为终点时记录路径。
  3. 剪枝无效路径:跳过越界、撞墙或已访问的位置。
  4. 回溯恢复状态:递归返回后,将当前位置标记为未访问。

示例代码(伪代码)

def dfs(x, y, path, visited):
    if (x, y) == (m-1, n-1):
        print(path)
        return
    for dx, dy in directions:
        nx, ny = x + dx, y + dy
        if 0 <= nx < m and 0 <= ny < n and grid[nx][ny] == 0 and not visited[nx][ny]:
            visited[nx][ny] = True
            path.append((nx, ny))
            dfs(nx, ny, path, visited)
            path.pop()
            visited[nx][ny] = False

总结与期望

在这里插入图片描述
深度优先搜索作为一种基础且强大的搜索算法,在解决各类路径搜索问题中展现出独特的优势。通过马走日和走迷宫这两个实例,我们深入理解了 DFS 的工作原理、实现步骤以及在实际应用中的注意事项 。在马走日的问题中,我们利用 DFS 探索马在棋盘上的所有可能移动路径,计算遍历整个棋盘的途径总数,这体现了 DFS 在处理具有特定规则的移动和状态空间搜索问题上的有效性 。而在走迷宫的场景里,DFS 帮助我们从起点出发,通过不断探索和回溯,寻找通往终点的路径,展示了其在解决复杂空间搜索问题的能力 。

DFS 的核心在于递归探索和回溯机制,这使得它能够全面地搜索所有可能的路径。同时,剪枝优化、避免重复访问和边界条件处理等注意事项,对于提高 DFS 的效率和正确性至关重要 。在未来的学习和实践中,我们可以进一步探索 DFS 在更复杂场景下的应用,比如在图论中寻找连通分量、检测环路等问题 。此外,将 DFS 与其他算法相结合,如与启发式搜索算法结合,可能会产生更高效的解决方案 。随着计算机技术的不断发展,DFS 在人工智能、游戏开发、网络分析等领域的应用前景也将更加广阔 。

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

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

相关文章

[c语言日寄]在不完全递增序中查找特定要素

【作者主页】siy2333 【专栏介绍】⌈c语言日寄⌋&#xff1a;这是一个专注于C语言刷题的专栏&#xff0c;精选题目&#xff0c;搭配详细题解、拓展算法。从基础语法到复杂算法&#xff0c;题目涉及的知识点全面覆盖&#xff0c;助力你系统提升。无论你是初学者&#xff0c;还是…

计算机视觉-局部特征

一、局部特征 1.1全景拼接 先用RANSAC估计出变换&#xff0c;就可以拼接两张图片 ①提取特征 ②匹配特征 ③拼接图像 1.2 点的特征 怎么找到对应点&#xff1f;&#xff08;才能做点对应关系RANSAC&#xff09; &#xff1a;特征检测 我们希望找到的点具有的特征有什么特…

实践记录-NAS入手前后的记录-关于设备选型的练习

快速回顾 知道nas是干啥的不&#xff0c;你买这东西准备干啥&#xff1f;你准备花多少预算啊&#xff1f;在配置性能/价格/需求之间做个取舍和平衡&#xff1b;看看设备到底怎么样&#xff1f;入手体验如何&#xff1f; 参考来源 服务器和网络设备的技术方案设计和设备选型的…

机器学习 - 词袋模型(Bag of Words)实现文本情感分类的详细示例

为了简单直观的理解模型训练&#xff0c;我这里搜集了两个简单的实现文本情感分类的例子&#xff0c;第一个例子基于朴素贝叶斯分类器&#xff0c;第二个例子基于逻辑回归&#xff0c;通过这两个例子&#xff0c;掌握词袋模型&#xff08;Bag of Words&#xff09;实现文本情感…

评估多智能体协作网络(MACNET)的性能:COT和AUTOGPT基线方法

评估多智能体协作网络(MACNET)的性能 方法选择:选择COT(思维链,Chain of Thought)、AUTOGPT等作为基线方法。 COT是一种通过在推理过程中生成中间推理步骤,来增强语言模型推理能力的方法,能让模型更好地处理复杂问题,比如在数学问题求解中,展示解题步骤。 AUTOGPT则是…

服务器中部署大模型DeepSeek-R1 | 本地部署DeepSeek-R1大模型 | deepseek-r1部署详细教程

0. 部署前的准备 首先我们需要足够算力的机器&#xff0c;这里我在vultr中租了有一张A16显卡一共16GB显存的服务器作为演示。部署的模型参数为14b的。如果需要部署满血版本671b的&#xff0c;需要更大的算力支持&#xff0c;这里由于是个人资金有限&#xff0c;就演示14b的部署…

chrome://version/

浏览器输入&#xff1a; chrome://version/ Google浏览器版本号以及安装路径 Google Chrome131.0.6778.205 (正式版本) &#xff08;64 位&#xff09; (cohort: Stable) 修订版本81b36b9535e3e3b610a52df3da48cd81362ec860-refs/branch-heads/6778_155{#8}操作系统Windows…

web集群(LVS-DR)

LVS是Linux Virtual Server的简称&#xff0c;也就是Linux虚拟服务器, 是一个由章文嵩博士发起的自由软件项 目&#xff0c;它的官方站点是 www.linuxvirtualserver.org。现在LVS已经是 Linux标准内核的一部分&#xff0c;在 Linux2.4内核以前&#xff0c;使用LVS时必须要重新编…

Python+appium实现自动化测试

目录 一、工具与环境准备 二、开始测试 1、插上手机&#xff0c;打开usb调试&#xff0c;选中文件传输&#xff0c;我这里用华为手机为例 2、启动Appium Server GUI​编辑 3、启动 Inspector Session 4、录制脚本 使用Python和Appium进行自动化测试是一种常见的移动应用…

光谱相机在天文学领域的应用

天体成分分析 恒星成分研究&#xff1a;恒星的光谱包含了其大气中各种元素的吸收和发射线特征。通过光谱相机精确测量这些谱线&#xff0c;天文学家能确定恒星大气中氢、氦、碳、氮、氧等元素的含量。如对太阳的光谱分析发现&#xff0c;太阳大气中氢元素占比约 71%&#xff0…

Java 设计模式之桥接模式

文章目录 Java 设计模式之桥接模式概述UML代码实现 Java 设计模式之桥接模式 概述 桥接模式(Bridge)&#xff1a;将抽象部分与它的实现部分分离&#xff0c;使它们都可以独立地变化。通过桥接模式&#xff0c;可以避免类爆炸问题&#xff0c;并提高系统的可扩展性。 UML 核心…

Git | 相关命令

相关资料 官网Git 学习教程Git 入门指南Git 的奇技淫巧Git Extras git 命令行扩展工具配置 Git 处理行结束符Git 配置多个 SSH-Key下载相关 Windows 版下载镜像使用 jsdelivr 加速 Github 仓库资源 commit 常用的 type 常用 Git 命令 [xxx] 均为可选参数 git clone # 拷贝一…

【STM32】H743的以太网MAC控制器的一个特殊功能

调试743的MAC&#xff0c;翻阅手册的时候&#xff0c;发现了一个有意思的功能 混杂模式 H743的MAC控制器&#xff0c;可以设置为混杂模式&#xff0c;这就意味着它可以做一些网络监控的应用&#xff0c;譬如连接具备端口镜像功能的交换机&#xff0c;然后直接代替PC实现网络数据…

【Spring AI】基于SpringAI+Vue3+ElementPlus的QA系统实现(后端)

整理不易&#xff0c;请不要吝啬你的赞和收藏。 1. 前言 这篇文章将介绍如何基于 RAG 技术&#xff0c;使用 SpringAI Vue3 ElementPlus 实现一个 Q&A 系统。本文使用 deepseek 的 DeepSeek-V3 作为聊天模型&#xff0c;使用阿里百炼的 text-embedding-v3 作为向量模型&…

AI法理学与责任归属:技术演进下的法律重构与伦理挑战

文章目录 引言:智能时代的新型法律困境一、AI技术特性对传统法理的冲击1.1 算法黑箱与可解释性悖论1.2 动态学习系统的责任漂移1.3 多智能体协作的责任稀释二、AI法理学的核心争议点2.1 法律主体资格认定2.2 因果关系的技术解构2.3 过错标准的重新定义三、责任归属的实践案例分…

数值积分:通过复合梯形法计算

在物理学和工程学中&#xff0c;很多问题都可以通过数值积分来求解&#xff0c;特别是当我们无法得到解析解时。数值积分是通过计算积分区间内离散点的函数值来近似积分的结果。在这篇博客中&#xff0c;我将讨论如何使用 复合梯形法 来进行数值积分&#xff0c;并以一个简单的…

mybatis-plus逆向code generator pgsql实践

mybatis-plus逆向code generator pgsql实践 环境准备重要工具的版本供参考pom依赖待逆向的SQL 配置文件CodeGenerator配置类配置类说明 环境准备 重要工具的版本 jdk1.8.0_131springboot 2.7.6mybatis-plus 3.5.7pgsql 14.15 供参考pom依赖 <?xml version"1.0&quo…

RedHat8安装postgresql15和 postgis3.4.4记录及遇到的问题总结

安装包对照版本参考 UsersWikiPostgreSQLPostGIS – PostGIS 如果Red Hat系统上有旧版本的PostgreSQL需要卸载 在较新的Red Hat版本&#xff0c;使用dnf包管理器卸载&#xff1a;sudo dnf remove postgresql-server postgresql 旧版本&#xff0c;使用yum包管理器卸载 sudo y…

2024BaseCTF_week4_web上

继续&#xff01;冲冲冲 目录 圣钥之战1.0 nodejs 原型 原型链 原型链污染 回到题目 flag直接读取不就行了&#xff1f; 圣钥之战1.0 from flask import Flask,request import jsonapp Flask(__name__)def merge(src, dst):for k, v in src.items():if hasattr(dst, __geti…

leetcode:627. 变更性别(SQL解法)

难度&#xff1a;简单 SQL Schema > Pandas Schema > Salary 表&#xff1a; ----------------------- | Column Name | Type | ----------------------- | id | int | | name | varchar | | sex | ENUM | | salary | int …