7-30 目录树
分数 30
作者 DS课程组
单位 浙江大学
在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
* 本题考查普通树(即不是二叉树)的建立与遍历;
* 普通树的静态写法,不用链表来写,儿子节点有超过两个的时候,有map,vector或者set来
* 存储比较方便,具体 child 类型根据题目定义;
* 本题的child 类型用 map<PIS,int> 来定义,PIS第一个类型是int,表示此字符串的优先级,
* 当是子目录时为0,当表示文件时为1,因为pair默认排序是按照第一个值从小到大排序,如果
* 第一个值相等再按照第二个值从小到大排序,这就刚好符合题目的要求;
* map的第二个类型是 int 表示此字符串在 tree 数组中的下标位置;
*
* 每一句相对文件目录或名称将其分解插入带 tree 树中,最后得到了整棵树,将其进行前序遍历
* 即可得到正确答案,当然,别忘了空格,这就在结构体中加入一个变量来表示此字符串的空格数;
* 此字符串比父亲节点的空格数多二。
/**
* 本题考查普通树(即不是二叉树)的建立与遍历;
* 普通树的静态写法,不用链表来写,儿子节点有超过两个的时候,有map,vector或者set来
* 存储比较方便,具体 child 类型根据题目定义;
* 本题的child 类型用 map<PIS,int> 来定义,PIS第一个类型是int,表示此字符串的优先级,
* 当是子目录时为0,当表示文件时为1,因为pair默认排序是按照第一个值从小到大排序,如果
* 第一个值相等再按照第二个值从小到大排序,这就刚好符合题目的要求;
* map的第二个类型是 int 表示此字符串在 tree 数组中的下标位置;
*
* 每一句相对文件目录或名称将其分解插入带 tree 树中,最后得到了整棵树,将其进行前序遍历
* 即可得到正确答案,当然,别忘了空格,这就在结构体中加入一个变量来表示此字符串的空格数;
* 此字符串比父亲节点的空格数多二。
*/
#include <iostream>
#include <map>
#include <algorithm>
#include <vector>
#include <cmath>
using namespace std;
typedef pair<int,string> PIS;
struct Node
{
string d;
int spa;
map<PIS,int> child;
};
const int maxn = 1e5;
Node tree[maxn];
int idx = 1; //下标从1开始,下标0存储根目录
int insert(int root,PIS v)
{
tree[root].child.insert({v,idx});
tree[idx].d = v.second;
tree[idx].spa = tree[root].spa + 2; //空格加二
tree[idx].child.clear();
return idx++;
}
void update(vector<PIS> &vec)
{
int index = 0;
for(int i = 0;i<vec.size();++i)
{
auto pos = tree[index].child.find(vec[i]);
if(pos == tree[index].child.end())
{
for(;i<vec.size();++i)
index = insert(index,vec[i]);
}
else
index = pos -> second;
}
}
//树的先根遍历与树的DFS的序列是一样的;
void pretraver(int root)
{
string temp(tree[root].spa , ' ');
cout << temp;
cout << tree[root].d << endl;
if(tree[root].child.size() == 0)
return;
for(auto v:tree[root].child)
{
int pos = v.second;
pretraver(pos);
}
}
int main()
{
int n;
cin >> n;
tree[0].d = "root";
tree[0].spa = 0;
tree[0].child.clear();
for(int i = 0;i < n;++ i)
{
string s;
cin >> s;
vector<PIS> vec;
for(int j = 0;j<s.size();++j)
{
int num = 0;
int k = j;
while(k<s.size() && isalpha(s[k++]))
++num;
string t = s.substr(j,num); //分解文件目录
PIS temp;
if(s[k-1] == '\\') //此自符串是子目录
temp = {0,t};
else
temp = {1,t}; //否则此字符串便是文件名
vec.push_back(temp);
j = k-1;
}
update(vec);
}
pretraver(0);
return 0 ;
}