目录树的建立和输出

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


  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值