在ZIP归档文件中,保留着所有压缩文件和目录的相对路径和名称。当使用WinZIP等GUI软件打开ZIP归档文件时,可以从这些信息中重建目录的树状结构。请编写程序实现目录的树状结构的重建工作。
输入格式说明:
输入首先给出正整数N(<=104),表示ZIP归档文件中的文件和目录的数量。随后N行,每行有如下格式的文件或目录的相对路径和名称(每行不超过260个字符):
1) 路径和名称中的字符仅包括英文字母(区分大小写);
2) 符号“\”仅作为路径分隔符出现;
3) 目录以符号“\”结束;
4) 不存在重复的输入项目;
5) 整个输入大小不超过2MB。
输出格式说明:
假设所有的路径都相对于root目录。从root目录开始,在输出时每个目录首先输出自己的名字,然后以字典序输出所有子目录,然后以字典序输出所有文件。注意,在输出时,应根据目录的相对关系使用空格进行缩进,每级目录或文件比上一级多缩进2个空格。
样例输入与输出:
序号 | 输入 | 输出 |
1 | 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 |
2 | 1 z\ | root z |
1、首先建立目录树。将输入的每个字符串插入到已有的目录树中,插入时将字符串的前缀与目录树的结点一层一层往下匹配,失配时创建新的目录和文件。
2、后序遍历目录树,对每个结点的子目录和子文件进行排序。
3、先序遍历进行输出。
/*2015.8.9cyq*/
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <fstream>
using namespace std;
//ifstream fin("case1.txt");
//#define cin fin
struct TNode{
string name;
bool isDoc;//true表示文件,false表示目录
vector<TNode*> next;
TNode(string s):name(s),isDoc(false){}
};
//寻找s中第一个'\'的位置并对s进行截取得到后段,前段用sHead返回
//函数返回第一个'\'的位置,若找不到返回-1
int findPos(string &s,string &sHead){
int pos=0;
int n=s.size();
for(pos=0;pos<n;pos++){
if(s[pos]=='\\')
break;
}
if(pos==n){
sHead=s;
s.clear();
return -1;
}
sHead=s.substr(0,pos);
if(pos==n-1)
s.clear();
else
s=s.substr(pos+1);
return pos;
}
//将字符串s插入以root为根的树
void insert2Tree(string &s,TNode *&root){
string sHead;
int pos=findPos(s,sHead);//sHead返回前段,s返回后段
TNode* tmp=new TNode(sHead);//前缀生成一个新结点
if(pos==-1)
tmp->isDoc=true;
int i;
for(i=0;i< root->next.size();i++){//检测是否前缀匹配且都是目录
if((root->next)[i]->name==tmp->name && !(root->next)[i]->isDoc && !tmp->isDoc){
if(!s.empty())
insert2Tree(s,(root->next)[i]);//从已有目录继续往下查找
break;
}
}
//匹配不到
if(i==root->next.size()){
root->next.push_back(tmp);//创建新的目录或文件
if(!s.empty())
insert2Tree(s,tmp);//继续往下创建
}
}
bool cmp(const TNode *a,const TNode *b){
if(!a->isDoc && b->isDoc)
return true;
else if((a->isDoc&&b->isDoc)||(!a->isDoc&&!b->isDoc)){
if(a->name < b->name)
return true;
}
return false;
}
void postOrder(TNode *&root){
if(!root->next.empty()){
for(auto it=root->next.begin();it!=root->next.end();++it)
postOrder(*it);
sort(root->next.begin(),root->next.end(),cmp);
}
}
void dfs(TNode *&root,int &blank){
for(int i=0;i<blank;i++)
cout<<" ";
cout<<root->name<<endl;
blank+=2;
for(auto it=root->next.begin();it!=root->next.end();++it)
dfs(*it,blank);
blank-=2;
}
int main(){
int N;
cin>>N;
string s;
TNode a("root");
TNode *root=&a;
while(N--){//建立目录树
cin>>s;
insert2Tree(s,root);
}
postOrder(root);//后序遍历对每个结点的子目录和子文件进行排序
int blank=0;
dfs(root,blank);//先序遍历输出结果
return 0;
}