在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\
输出样例:
rootadzabcabcddcb
代码实现:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct Tnode* BT;
struct Tnode
{char *name;BT left;BT right;int type;
};
BT Buildroot(char* f1)
{char* str=(char*)malloc(5*sizeof(char));BT root=(BT)malloc(sizeof(struct Tnode));root->left=root->right=NULL;root->type=1;for(int i=0;i<4;i++){str[i]=f1[i];}str[4]='\0';root->name=str;return root;
}
BT createNode(char* str,int t)
{BT newnode=(BT)malloc(sizeof(struct Tnode));newnode->left=NULL;newnode->right=NULL;newnode->type=t;newnode->name=str;return newnode;
}
char* build(int start,int end,char* path)
{int len=end-start;char* str=(char*)malloc((len+1)*sizeof(char));for(int i=0;i<len;i++){str[i]=path[start+i];}str[len]='\0';return str;
}
BT Insert(char* str,BT pos,int t);
void Traversal(BT root,int floor);int main()
{int n;scanf("%d",&n);char f1[5]="root";BT root=Buildroot(f1);while(n--){char path[261];scanf("%s",path);BT pos=root;int l=strlen(path);int i=0,start=0,end=0;while(i<l){if(path[i]=='\\'){//插入目录end=i;char *str=build(start,end,path);pos=Insert(str,pos,1);start=i+1;}i++;}if(path[start]!='\0'){//插入文件char* str=build(start,l,path);pos=Insert(str,pos,0);}}Traversal(root,0);return 0;
}
BT Insert(char* str,BT pos,int t)
{//依题意可知插入的节点一定比pos低一级if(pos==NULL)return NULL;if(pos->left==NULL){BT Node=createNode(str,t);pos->left=Node;return pos->left;}//如果该节点有孩子BT child=pos->left,pre=pos;while(child!=NULL&&((child->type>t)||((child->type==t)&&strcmp(str,child->name)>0))){//比较文件与目录的优先级以及名字的字典序pre=child;child=child->right;}if(child==NULL){pre->right=createNode(str,t);return pre->right;}if(child->type==t&&(strcmp(child->name,str)==0)){//说明该节点已经存在return child;}else{BT temp=createNode(str,t);if(strcmp(pre->name,pos->name)==0){//特殊情况排在第一位的子节点temp->right=pre->left;pre->left=temp;}else{temp->right=pre->right;pre->right=temp;}return temp;}
}
void Traversal(BT root,int floor)
{if(root==NULL)return;for(int i=0;i<floor;i++){printf(" ");}printf("%s\n",root->name);Traversal(root->left,floor+2);Traversal(root->right,floor);return;
}