在ZIP归档文件中,保留着所有压缩文件和目录的相对路径和名称。当使用WinZIP等GUI软件打开ZIP归档文件时,可以从这些信息中重建目录的树状结构。请编写程序实现目录的树状结构的重建工作。
输入格式:
输入首先给出正整数N(≤10^4 ),表示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
#include <iostream>
#include <vector>
#include <algorithm>
#include <set>
#include <string>
using namespace std;
struct Node {
string data;
vector<Node*>link;
set<string>file;
};
bool cmp(const Node* a, const Node* b) {
return (*a).data < (*b).data;
}
void insert(Node* root, string str) { //把str字段插入,root目录下
if (str.empty())
return;
Node* n = new Node();
int index = str.find('\\'); //返回第一个'\'出现的下标,若找不到返回-1
if (index != -1) {
string s = str.substr(0, index); //截取s=str[0,index)
n->data = s;
int flag = 0;
for (auto& it : root->link)
if (it->data == n->data) //若之前出现过该文件夹,改变指针指向
n = it,
flag = 1;
if (!flag) //未出现过,加入文件夹列表
root->link.push_back(n);
str = str.substr(index + 1); //取第一个'\'之后的字段
insert(n, str); //把str[index+1,str.size())字段插入当前找到的文件夹str下
}
else //返回-1说明str要么是空,要么是一个文件
root->file.insert(str);
return;
}
void dfs(Node& root) {
sort(root.link.begin(), root.link.end(), cmp); //对当前目录下的文件夹按自定义cmp排序
for (auto& it : root.link)
dfs(*it);
}
void print(Node root, int n) {
for (int i = 0; i < n; ++i)
cout << " ";
cout << root.data << endl;
for (auto& it : root.link)
print(*it, n + 1);
for (auto& it : root.file) {
for (int i = 0; i < n + 1; ++i)
cout << " ";
cout << it << endl;
}
}
int main() {
int N;
string str;
Node root, n;
root.data = "root";
cin >> N;
while (N--) {
cin >> str;
insert(&root, str);
}
dfs(root);
print(root, 0);
return 0;
}