7-30 目录树(PTA中文算法集)(多叉树的静态写法)

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 ;
        
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值