PTA 数据结构与算法 7-30 目录树

如有不对,不吝赐教
进入正题:
在ZIP归档文件中,保留着所有压缩文件和目录的相对路径和名称。当使用WinZIP等GUI软件打开ZIP归档文件时,可以从这些信息中重建目录的树状结构。请编写程序实现目录的树状结构的重建工作。

输入格式:
输入首先给出正整数N(≤10^4​​),表示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

这道题目其实就是构建一棵树,不过树的左右节点是不同的(在我的方案里面),我的方案是参考了将任一一棵多叉树转换成一棵二叉树的方案,在这道题里面,就是一个子树放目录,另一个子树放文件。
这里稍微注意一下输出,同级的文件和目录是先输出目录,再来文件。输出时可以用递归,也可以迭代。

给出代码:

#include<stdio.h>
#include<malloc.h>
#include<string.h>

struct File{
int space;         //到这个文件需要打印的空格数目
char name[261];
struct File *sibFile;   //同级文件链表
};

struct Catalog{
int space;         //到该目录需要打印的空格数目
char name[261];
struct Catalog *sonCat;    //子目录分支
struct Catalog *sibCat;     //同级目录分支 按字典序排序
struct File *file;          //文件分支
};

struct Catalog *Add(struct Catalog *root,char *input);
struct Catalog *AddCat(struct Catalog *root,char *name,char *input);
struct Catalog *AddFile(struct Catalog *root,char *name);
void Print(struct Catalog *root);

int main(void)
{
    int N,i;
    struct Catalog *root;   //目录树的根
    char input[261];        //每行最多260个字符
    char temp[5]="root";
    scanf("%d",&N);

    root=(struct Catalog *)malloc(sizeof(struct Catalog));
    root->file=(struct File *)malloc(sizeof(struct File));
    root->sibCat=(struct Catalog *)malloc(sizeof(struct Catalog));
    root->file=NULL;
    root->sibCat=NULL;
    root->sonCat=NULL;
    strcpy(root->name,temp);
    root->space=0;            //初始化根节点

    for(i=0;i<N;i++){
      scanf("%s",input);
      root=Add(root,input);
    }

    Print(root);

    return 0;
}

struct Catalog *Add(struct Catalog *root,char *input)
{
    int i,j;
    char name[261];    //提取出的姓名

    for(i=0,j=0;'\\'!=input[i]&&input[i];i++)   //看有没有问题
      name[j++]=input[i];
    name[j]='\0';

    if('\\'==input[i])      //表示是目录
      root=AddCat(root,name,input+i+1);   //略过'\\'
    else
      root=AddFile(root,name);

    return root;
}

struct Catalog *AddCat(struct Catalog *root,char *name,char *input)
{
    struct Catalog *cur=root->sonCat;

    struct Catalog *newOne;
    newOne=(struct Catalog *)malloc(sizeof(struct Catalog));
    newOne->sibCat=(struct Catalog *)malloc(sizeof(struct Catalog));
    newOne->sonCat=(struct Catalog *)malloc(sizeof(struct Catalog));
    newOne->file=(struct File *)malloc(sizeof(struct File));
    newOne->sibCat=NULL;
    newOne->sonCat=NULL;
    newOne->space=root->space+2;
    newOne->file=NULL;
    strcpy(newOne->name,name);           //初始化新节点

    do{
      if(!cur){
        root->sonCat=newOne;
        break;
      }  //子目录树为空树

      if(strcmp(cur->name,name)>0){
        newOne->sibCat=cur;
        root->sonCat=newOne;
        break;
      }      //比第一个目录的字典序小

      if(!strcmp(cur->name,name)){
        cur=Add(cur,input);
        free(newOne);
        return root;
      }    //输入的就是目录树的第一个目录

      while(cur->sibCat&&strcmp(cur->sibCat->name,name)<0)
        cur=cur->sibCat;    //找到插入的位置

      if(cur->sibCat){
        if(!strcmp(cur->sibCat->name,name)){
          cur->sibCat=Add(cur->sibCat,input);
          return root;
        }    //和其字典序相等
        else{
          newOne->sibCat=cur->sibCat;
          cur->sibCat=newOne;
        }
      }   //插入位置在树的中间
      else
        cur->sibCat=newOne;
    }while(0);

    if(input[0])   //还有子目录或者文件的话
      newOne=Add(newOne,input);

    return root;
}

struct Catalog *AddFile(struct Catalog *root,char *name)
{
    if(!name)      //没有添加的文件分支
      return root;

    struct File *cur=root->file;
    struct File *newOne;

    newOne=(struct File *)malloc(sizeof(struct File));
    newOne->sibFile=(struct File *)malloc(sizeof(struct File));
    strcpy(newOne->name,name);
    newOne->sibFile=NULL;
    newOne->space=root->space+2;    //初始化新节点

    if(!cur){
      root->file=newOne;
      return root;
    }    //文件树为空

    if(strcmp(cur->name,name)>0){
      newOne->sibFile=cur;
      root->file=newOne;
      return root;
    }             //输入的文件比第一个文件名字典序更小

    while(cur->sibFile&&strcmp(cur->sibFile->name,name)<0)
      cur=cur->sibFile;
                        //找到插入位置
    if(!cur->sibFile)
      cur->sibFile=newOne;
    else{
      newOne->sibFile=cur->sibFile;
      cur->sibFile=newOne;
    }

    return root;
}

void Print(struct Catalog *root)
{
    if(!root)
      return ;

    short i;
    struct Catalog *curCat=root->sonCat;
    struct File *curFile=root->file;

    for(i=0;i<root->space;i++)
      putchar(' ');
    printf("%s\n",root->name);   //输出当前根目录名称

    while(curCat){
      Print(root->sonCat);
      root->sonCat=curCat->sibCat;
      free(curCat);
      curCat=NULL;
      curCat=root->sonCat;
    }

    while(curFile){
      for(i=0;i<curFile->space;i++)
        putchar(' ');
      printf("%s\n",curFile->name);
      root->file=curFile->sibFile;
      free(curFile);
      curFile=NULL;
      curFile=root->file;
      }    //打印文档名字

    return ;
}

测试结果:
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值