1-10 目录树

在ZIP归档文件中,保留着所有压缩文件和目录的相对路径和名称。当使用WinZIP等GUI软件打开ZIP归档文件时,可以从这些信息中重建目录的树状结构。请编写程序实现目录的树状结构的重建工作。

输入格式:

输入首先给出正整数N(≤104),表示ZIP归档文件中的文件和目录的数量。随后N行,每行有如下格式的文件或目录的相对路径和名称(每行不超过260个字符):

  • 路径和名称中的字符仅包括英文字母(区分大小写);
  • 符号"\"仅作为路径分隔符出现;
  • 目录以符号"\"结束;
  • 不存在重复的输入项目;
  • 整个输入大小不超过2MB。

输出格式:

假设所有的路径都相对于root目录。从root目录开始,在输出时每个目录首先输出自己的名字,然后以字典序输出所有子目录,然后以字典序输出所有文件。注意,在输出时,应根据目录的相对关系使用空格进行缩进,每级目录或文件比上一级多缩进2个空格。

输入样例:

复制代码
7
b
c\
ab\cd
a\bc
ab\d
a\d\a
a\d\z\

输出样例:

复制代码
root
  a
    d
      z
      a
    bc
  ab
    cd
    d
  c
  b

一、问题核心与难点

本任务要求根据给定的文件路径列表,构建完整的目录树结构,并按照特定格式输出。主要挑战在于:

  1. ​路径层级解析​:需要正确处理路径分隔符"",识别目录与文件
  2. ​树形结构构建​:动态创建多级目录节点
  3. ​字典序输出​:保证同级目录和文件的顺序正确

二、数据结构设计

采用树形结构进行存储,每个节点包含:

复制代码
struct Node {
    string name;
    map<string, Node*> dirs;  // 有序存储子目录
    map<string, Node*> files; // 有序存储文件
};

使用map容器实现自动字典序排序,其中:

  • dirs存储下级目录节点
  • files存储当前目录下的文件

三、实现流程详解

1. 路径分割处理

通过split函数解析路径字符串:

复制代码
vector<string> split(const string &s) {
    vector<string> tokens;
    // 处理逻辑:遇到"\"分割路径组件
    // 保留空组件用于目录判断
}

该函数将类似"a\d\z"的路径转换为"a", "d", "z",同时通过原字符串末尾的""判断是否为目录。

2. 树形结构构建
复制代码
Node* current = root;
for (auto &comp : tokens) {
    if (需要创建目录) {
        current->dirs[comp] = new Node(comp);
    }
    current = 下一级节点;
}

逐级创建目录节点,文件存储在终末节点的files集合中。

3. 递归输出逻辑
复制代码
void printTree(Node* node, int indent) {
    // 输出当前节点
    // 递归输出子目录
    // 输出文件
}

采用深度优先遍历,通过缩进参数控制格式,实现:

  • 目录优先于文件输出
  • 同级元素按字母序排列

四、关键实现技巧

  1. ​目录/文件区分​:通过原始路径的结尾字符判断类型
  2. ​自动排序机制​:利用map的有序特性简化排序逻辑
  3. ​内存管理​:使用裸指针需注意内存释放(实际应用中建议使用智能指针)

五、示例分析

输入样例:

复制代码
a\d\z\

处理流程:

  1. 识别为目录
  2. 分割为"a", "d", "z"
  3. 在root下创建a节点
  4. 在a节点下创建d节点
  5. 在d节点下创建z目录节点

完整代码:

复制代码
#include <iostream>
#include <vector>
#include <map>
#include <algorithm>
#include <string>

using namespace std;

struct Node {
    string name;
    map<string, Node*> dirs;
    map<string, Node*> files;

    Node(string n) : name(n) {}
};

vector<string> split(const string &s) {
    vector<string> tokens;
    string token;
    for (char c : s) {
        if (c == '\\') {
            if (!token.empty()) {
                tokens.push_back(token);
                token.clear();
            }
        } else {
            token += c;
        }
    }
    if (!token.empty()) {
        tokens.push_back(token);
    }
    return tokens;
}

void printTree(Node* node, int indent) {
    if (indent == 0) {
        cout << node->name << endl;
    } else {
        cout << string(indent * 2, ' ') << node->name << endl;
    }

    for (auto &dir : node->dirs) {
        printTree(dir.second, indent + 1);
    }

    // 输出子文件
    for (auto &file : node->files) {
        cout << string((indent + 1) * 2, ' ') << file.second->name << endl;
    }
}

int main() {
    int n;
    cin >> n;
    cin.ignore(); // 忽略换行符

    Node* root = new Node("root");

    for (int i = 0; i < n; ++i) {
        string s;
        getline(cin, s);
        bool isDir = !s.empty() && s.back() == '\\';
        vector<string> tokens = split(s);

        Node* current = root;
        for (size_t j = 0; j < tokens.size(); ++j) {
            string comp = tokens[j];
            bool isLast = (j == tokens.size() - 1);

            if (isLast) {
                if (isDir) {
                    if (current->dirs.find(comp) == current->dirs.end()) {
                        current->dirs[comp] = new Node(comp);
                    }
                    current = current->dirs[comp];
                } else {
                    current->files[comp] = new Node(comp);
                }
            } else {
                if (current->dirs.find(comp) == current->dirs.end()) {
                    current->dirs[comp] = new Node(comp);
                }
                current = current->dirs[comp];
            }
        }
    }

    printTree(root, 0);

    return 0;
}
相关推荐
学习中.........4 小时前
Transformer 训练资源估算:以 CS336 GPT-2 XL 配置为例
人工智能·python·算法·机器学习·自然语言处理
kkkkkkkkkk_Z9 小时前
学嵌入式和C语言编程数据结构|学习日记Day22:栈,二叉树,哈希存储
c语言·数据结构·学习
覆东流9 小时前
7.Java数组
java·开发语言·后端
m0_719084119 小时前
限流和获取请求ip的方法
java
Navigator_Z9 小时前
LeetCode //C - 1206. Design Skiplist
c语言·算法·leetcode
码行山野赴时序归途10 小时前
三道经典数组题:从暴力到最优的算法思维
c语言·开发语言·数据结构·算法·leetcode
lzhdim10 小时前
提高 SQL 语句执行速度的方法
java·开发语言·数据库·sql·oracle
徐小夕10 小时前
3分钟从想法到Agent上线:我们开源了一款AI可视化工作流“IDE”
前端·算法·github
深漂的华哥11 小时前
Ruoyi-Plus前后端分离场景下,数据加密传输
java·spring boot·后端·开源·maven·ruoyi
sel_911 小时前
【强化学习】Hands-on Modern RL项目实践|OPD 算法完整解析
人工智能·深度学习·算法·机器学习·语言模型