【IO编程】深度优先遍历

深度优先遍历目录(Depth-First Traversal) 是一种递归或栈式的目录遍历方法,优先深入到子目录中,再回溯到父目录继续遍历其他子目录。这是一种常见的文件系统操作,适用于查找文件、统计目录大小等场景。

深度优先遍历完整思路
  1. 递归式遍历:优先进入子目录,完成当前目录所有子目录的遍历后再返回上一层。
  2. 适合处理嵌套结构:目录树是一个递归结构,深度优先遍历特别适用于这种嵌套结构。
  3. 有序性
    • 由上至下:先访问父目录,再依次深入子目录。
    • 从左至右:每层目录按照特定顺序(如字母顺序)排列。
代码详情具体实现深度优先遍历目录的过程(通过代码的编程思路直观的理解深度优先的编程思路)

在 C语言 中,可以使用 dirent.h 提供的函数(如 opendir()readdir())来遍历目录。同时可以使用递归来实现深度优先遍历。

#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <sys/stat.h>
#include <string.h>

// 深度优先遍历目录
void dfs_directory(const char *path, int depth) {
    DIR *dir = opendir(path);
    if (dir == NULL) {
        perror("opendir");
        return;
    }

    struct dirent *entry;
    while ((entry = readdir(dir)) != NULL) {
        // 跳过当前目录和父目录
        if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
            continue;
        }

        // 构造完整路径
        char full_path[1024];
        snprintf(full_path, sizeof(full_path), "%s/%s", path, entry->d_name);

        // 判断是否为目录
        struct stat st;
        if (stat(full_path, &st) == 0 && S_ISDIR(st.st_mode)) {
            // 打印目录并递归进入
            printf("%*s[DIR] %s\n", depth * 2, "", full_path);
            dfs_directory(full_path, depth + 1);
        } else {
            // 打印文件
            printf("%*s[FILE] %s\n", depth * 2, "", entry->d_name);
        }
    }

    closedir(dir);
}

int main(int argc, char *argv[]) {
    const char *start_path = argc > 1 ? argv[1] : ".";
    dfs_directory(start_path, 0);
    return 0;
}

再使用 Python 实现,因为 python 轻量级语言,实现过程更为简洁:
Python 的标准库 os 和 os.path 提供了文件和目录操作的相关工具,可以轻松实现深度优先遍历目录。
代码逻辑(递归实现)

import os

def dfs_directory(path, depth=0):
    # 打印当前目录
    print("  " * depth + f"[DIR] {path}")

    # 遍历当前目录的所有文件和子目录
    for entry in os.listdir(path):
        full_path = os.path.join(path, entry)
        # 如果是目录,则递归遍历
        if os.path.isdir(full_path):
            dfs_directory(full_path, depth + 1)
        else:
            # 如果是文件,则打印文件路径
            print("  " * (depth + 1) + f"[FILE] {entry}")

# 调用函数
start_path = "./test_directory"  # 替换为需要遍历的目录
dfs_directory(start_path)

我们先假设目录结构如下:

test_directory/
├── file1.txt
├── subdir1/
│   ├── file2.txt
│   └── file3.txt
└── subdir2/
    └── subsubdir/
        └── file4.txt

输出:

[DIR] ./test_directory
  [FILE] file1.txt
  [DIR] ./test_directory/subdir1
    [FILE] file2.txt
    [FILE] file3.txt
  [DIR] ./test_directory/subdir2
    [DIR] ./test_directory/subdir2/subsubdir
      [FILE] file4.txt

另一种实现方式:栈实现(非递归)
深度优先遍历也可以通过栈来实现,避免递归调用的栈深度限制。

import os

def dfs_directory_stack(path):
    # 使用栈实现深度优先遍历
    stack = [path]

    while stack:
        current_path = stack.pop()
        if os.path.isdir(current_path):
            print(f"[DIR] {current_path}")
            # 将当前目录的内容加入栈
            for entry in sorted(os.listdir(current_path), reverse=True):
                stack.append(os.path.join(current_path, entry))
        else:
            print(f"[FILE] {current_path}")

# 调用函数
start_path = "./test_directory"  # 替换为需要遍历的目录
dfs_directory_stack(start_path)

也可以直接使用 Shell 实现,不用写代码,Shell 脚本中可以使用 find 命令来实现深度优先遍历:

find ./test_directory

输出:

./test_directory
./test_directory/file1.txt
./test_directory/subdir1
./test_directory/subdir1/file2.txt
./test_directory/subdir1/file3.txt
./test_directory/subdir2
./test_directory/subdir2/subsubdir
./test_directory/subdir2/subsubdir/file4.txt
深度优先遍历的应用场景
  • 文件搜索:
    • 在复杂的目录树中查找特定文件或文件类型。
    • 示例:查找所有 .txt 文件:
import os

def find_txt_files(path):
    for root, dirs, files in os.walk(path):
        for file in files:
            if file.endswith(".txt"):
                print(os.path.join(root, file))

find_txt_files("./test_directory")
  • 目录大小统计:
    • 统计目录及其子目录的总大小。
    • 示例代码:
import os

def calculate_directory_size(path):
    total_size = 0
    for root, dirs, files in os.walk(path):
        for file in files:
            file_path = os.path.join(root, file)
            total_size += os.path.getsize(file_path)
    return total_size

print(f"Total size: {calculate_directory_size('./test_directory')} bytes")
  • 备份工具:遍历目录树并复制文件到备份位置。
  • 文件清理:删除某些特定类型的文件或空文件夹。
  • 目录树展示:以树状结构展示目录层级。

使用深度优先遍历具有诸多好处:递归实现方式与目录树结构天然契合,代码思路简单直观适合嵌套结构,能深入到子目录,适合操作深层嵌套的目录;占用资源少:在处理大目录时,深度优先遍历通常比广度优先遍历占用内存更少。不过,在应用过程中也需要注意一些可能会出现的问题:① 可能导致栈溢出:如果目录嵌套过深,递归实现可能导致栈溢出。② 目录顺序不固定:由于深度优先的遍历顺序,无法保证目录按字母顺序排列。

深度优先遍历目录是一种高效、灵活的目录操作方法,尤其适用于嵌套结构的文件系统。通过递归或栈实现深度优先遍历,可以方便地完成文件搜索、目录统计等任务。我们以上提供了三种不同的实现方式(但代码思路是一致的),综上。希望该内容能对你有帮助,感谢您的阅读!

以上。仅供学习与分享交流,请勿用于商业用途!转载需提前说明。

我是一个十分热爱技术的程序员,希望这篇文章能够对您有帮助,也希望认识更多热爱程序开发的小伙伴。
感谢!

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

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

相关文章

【2024年华为OD机试】 (CD卷,100分)- 最大N个数与最小N个数的和(Java JS PythonC/C++)

一、问题描述 题目描述 给定一个数组&#xff0c;编写一个函数来计算它的最大N个数与最小N个数的和。你需要对数组进行去重。 说明&#xff1a; 数组中数字范围 [0, 1000]最大N个数与最小N个数不能有重叠&#xff0c;如有重叠&#xff0c;输入非法返回 -1输入非法返回 -1 …

WINFORM - DevExpress -> DevExpress总结[安装、案例]

安装devexpress软件 路径尽量不换&#xff0c;后面破解不容易出问题 vs工具箱添加控件例如: ①使用控制台进入DevExpress安装目录: cd C:\Program Files (x86)\DevExpress 20.1\Components\Tools ②添加DevExpress控件&#xff1a; ToolboxCreator.exe/ini:toolboxcreator…

cursor+deepseek构建自己的AI编程助手

文章目录 准备工作在Cursor中添加deepseek 准备工作 下载安装Cursor &#xff08;默认安装在C盘&#xff09; 注册deepseek获取API key 在Cursor中添加deepseek 1、打开cursor&#xff0c;选择设置 选择Model&#xff0c;添加deepseek-chat 注意这里去掉其他的勾选项&…

《零基础Go语言算法实战》【题目 2-7】defer 关键字特性

《零基础Go语言算法实战》 【题目 2-7】defer 关键字特性 下面代码的输出是什么&#xff1f;请说明原因。 package main import ( "fmt" ) func main() { deferFunc() func deferFunc() { defer func() { fmt.Println("value1") }() defer func() {…

如何规模化实现完全自动驾驶?Mobileye提出解题“新”思路

在CES 2025上&#xff0c;Mobileye展示了端到端自动驾驶系统Mobileye Drive™&#xff0c;通过高度集成的传感器、算法和计算平台&#xff0c;可以实现自动驾驶功能的全覆盖。 Mobileye创始人兼首席执行官Amnon Shashua教授 期间&#xff0c;Mobileye创始人兼首席执行官Amnon …

腾讯云AI代码助手编程挑战赛-智能聊天助手

作品简介 本作品开发于腾讯云 AI 代码助手编程挑战赛&#xff0c;旨在体验腾讯云 AI 代码助手在项目开发中的助力。通过这一开发过程&#xff0c;体验到了 AI 辅助编程的高效性。 技术架构 前端: 使用 VUE3、TypeScript、TDesign 和 ElementUI 实现。 后端: 基于 Python 开发…

超大规模分类(三):KNN softmax

传统的分类损失计算输入数据和每个类别中心的距离&#xff0c;来优化模型的训练。KNN softmax通过选择和输入数据最相关的top-K个类别&#xff0c;仅计算输入数据和top-K个类别中心的距离&#xff0c;以减小计算量。 KNN softmax首次诞生于达摩院机器智能技术实验室发表的SIGKD…

MySQL素材怎么导入Navicat???

不管用什么方法都要先关掉MySQL服务&#xff0c;并且提前备份数据&#xff01; 1.有sql文件时候。 打开navicat&#xff0c;运行sql文件 然后点击后面三个点&#xff0c;选中要运行的sql文件&#xff0c;开始。 鼠标右键刷新一下&#xff0c;就能看到sql文件中的表了 2.没有s…

程序员独立开发竞品分析:确定网站使用什么建站系统

要确定一个网站使用的建站系统&#xff0c;可以通过以下几种方法尝试分析&#xff1a; 查看页面源代码&#xff1a; 打开网站&#xff0c;右键点击页面并选择“查看页面源代码”。在代码中查找一些常见的建站系统标志&#xff0c;例如&#xff1a; WordPress 的迹象&#xff1a…

Linux(Centos7)安装Mysql/Redis/MinIO

安装Mysql 安装Redis 搜索Redis最先版本所在的在线安装yum库 查看以上两个组件是否是开机自启 安装MinIO 开源的对象存储服务&#xff0c;存储非结构化数据&#xff0c;兼容亚马逊S3协议。 minio --help #查询命令帮助minio --server --help #查询--server帮助minio serve…

【DB-GPT】开启数据库交互新篇章的技术探索与实践

一、引言&#xff1a;AI原生数据应用开发的挑战与机遇 在数字化转型的浪潮中&#xff0c;企业对于智能化应用的需求日益增长。然而&#xff0c;传统的数据应用开发方式面临着诸多挑战&#xff0c;如技术栈复杂、开发周期长、成本高昂、难以维护等。这些问题限制了智能化应用的…

解决aerich init -t xx 报错ModuleNotFoundError: No module named ‘tomli_w‘

今天在学习fastapi的时候&#xff0c;发现一款数据库迁移工具&#xff0c;通过这个工具可以根据模型类来对数据库做出改变。 随跟着学: 在执行 aerich init -t settings.TORTOISE_ORM的时候&#xff0c; 彼其娘之。。 报了一些错误&#xff1a; Traceback (most recent ca…

.NET Core NPOI 导出图片到Excel指定单元格并自适应宽度

NPOI&#xff1a;支持xlsx&#xff0c;.xls&#xff0c;版本>2.5.3 XLS&#xff1a;HSSFWorkbook&#xff0c;主要前缀HSS&#xff0c; XLSX&#xff1a;XSSFWorkbook&#xff0c;主要前缀XSS&#xff0c;using NPOI.XSSF.UserModel; 1、导出Excel添加图片效果&#xff0…

浅谈云计算07 | 云安全机制

浅谈云计算安全机制&#xff1a;全方位守护云端世界 一、引言二、加密技术&#xff1a;数据的隐形护盾三、散列机制&#xff1a;数据完整性的忠诚卫士四、数字签名&#xff1a;数据来源与真伪的鉴定专家五、公钥基础设施&#xff08;PKI&#xff09;&#xff1a;信任的基石六、…

Unity 2d描边基于SpriteRender,高性能的描边解决方案

目标 以Unity默认渲染管线为例&#xff0c;打造不需要图片内边距&#xff0c;描边平滑&#xff0c;高性能的描边解决方案 前言 在2d游戏中经常需要给2d对象添加描边&#xff0c;来突出强调2d对象 当你去网上查找2d描边shader&#xff0c;移植到项目里面&#xff0c;大概率会…

Uniapp仿ChatGPT Stream流式输出(非Websocket)

Uniapp仿ChatGPT Stream流式输出&#xff08;非Websocket&#xff09; 前言&#xff1a;流式输出可以使用websocket也可以使用stream来实现EventSource是 HTML5 中的一个接口&#xff0c;用于接收服务器发送的事件流&#xff08;Server - Sent Events&#xff0c;SSE&#xff…

黑马linux入门笔记(01)初始Linux Linux基础命令 用户和权限 实用操作

B站 黑马程序员 的视频 BV1n84y1i7td 黑马程序员新版Linux零基础快速入门到精通&#xff0c;全涵盖linux系统知识、常用软件环境部署、Shell脚本、云平台实践、大数据集群项目实战等 增强自控力 冥想慢呼吸绿色锻炼充分休息减少决策次数优先做重要的事情(早晨)融入强自控群控…

当你不小心使用了MySQL的保留字作为字段名而导致你的SQL语法解析错误该怎么办!

问题举例&#xff1a; 你在尝试更新一个名为 desc 的字段时遇到了 SQL 语法错误。原因是 desc 是 MySQL 的保留字&#xff0c;通常用于表示 ORDER BY 子句中的降序&#xff08;DESC&#xff09;&#xff0c;因此直接使用 desc 作为字段名会导致 SQL 解析错误。如下图&#xff…

excel设置好的可选择列数据后,如何快速输入到单元格中?

当设置好列的【数据】-【数据有效性】-【序列】后&#xff0c;在单元格中输入可选择数据的开头&#xff0c;就会提示出对应的可选择数据&#xff0c;然后&#xff0c;按一下键盘上的【↓】键&#xff0c;再按回车&#xff0c;即可快速输入到单元格中。

2025封禁指定国家ip-安装xtables-addons记录

如何安装和使用 安装lux仓库(该仓库包含xtables-addons所需的依赖环境) # wget http://repo.iotti.biz/CentOS/7/noarch/lux-release-7-1.noarch.rpm # rpm -ivh lux-release-7-1.noarch.rpm 安装xtables-addons。注意&#xff1a;必须先安装kmod-xtables-addons&#xff0c;再…