7-9 目录树

在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

 很显然,这是一个森林结构,我们只需要在建好森林后,将每一个节点的孩子节点按照字典序进行排序,叶子节点(文件)最后输出。对于每一个节点结构体leaf=true代表它是一个叶子节点。在建树的过程中,每次提取一个文件/目录名后判断它的下一个字符是否是\,如果是,那么它是目录,否则是文件。

AC(Accept)代码:

#include<bits/stdc++.h>
using namespace std;
struct Tree {
    string val;
    bool leaf;
    map<string,Tree*,greater<string>>mp;
    Tree(string val,bool leaf):val(val),leaf(leaf) {};
};
auto cmp=[](pair<string,Tree*>& a,pair<string,Tree*>& b) {
        if(a.second->leaf==b.second->leaf) {
            return a.second->val<b.second->val;
        }
        return a.second->leaf<b.second->leaf;
};
void Print(Tree* root,int blank) {
    for(int i=0; i<blank; i++) {
        cout<<" ";
    }
    cout<<root->val<<endl;
    if(root->mp.size()==0) {
        return;
    }
    vector<pair<string,Tree*>>vec(root->mp.begin(),root->mp.end());
    sort(vec.begin(),vec.end(),cmp);
    for(auto it:vec) {
        Print(it.second,blank+2);
    }
}
int main() {
    int n;
    cin>>n;
    Tree* root=new Tree("root",true);
    for(int i=0; i<n; i++) {
        string word,s;
        cin>>s;
        Tree* pre=root;
        for(int j=0; j<s.size(); j++) {
            word="";
            while(j<s.size()&&s[j]!='\\') {
                word+=s[j];
                j++;
            }
            if(!pre->mp.count(word)) {
                pre->mp[word]=new Tree(word,false);
                if(s[j]!='\\')
                    pre->mp[word]->leaf=true;
            }
            pre=pre->mp[word];
        }
    }
    Print(root,0);
    return 0;
}

 

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值