pta 9 目录树 (30分) (树的遍历)

该博客介绍了如何根据ZIP归档文件中的信息重建目录树结构,重点在于理解输入输出格式,并使用递归进行先序遍历,按照字典序输出目录和文件。解题思路包括建树、排序和递归遍历的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


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

输入格式:

输入首先给出正整数N(\le 10^4104),表示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 <bits/stdc++.h>

using namespace std;
const int maxn=1e4;
char a[333];
struct p
{
    char str[333];
    int siz;
    int od;
    p*next[333];
};
int top;
bool cmp(p *a , p *b)
{
    if(a->od!=b->od)return a->od>b->od;
    else return strcmp(a->str,b->str)<0;
}
void pre(p*root)
{
    int i, j;
    for(i=0; i<top; i++)printf("  ");
    printf("%s\n", root->str);
    top++;
    char t[333];
    for(i=0; i<root->siz; i++)
    {
       sort(root->next, root->next+root->siz, cmp);
        pre(root->next[i]);

    }
    top--;
    return;
}
int main()
{

    int n;
    cin>>n;
    int i, j;
    p*root=(p*)malloc(sizeof(p));
    for(i=0; i<332; i++)root->next[i]=NULL;
    root->siz=0;
    strcpy(root->str, "root");
    int s=0, k;
    char e[333];
    p*q;
    top=0;
    for(i=0; i<n; i++)
    {
        q=root;
        scanf("%s", a);
        int siz;
        for(j=0; a[j]; j++)
        {
//            if(i==6)printf("%c", a[j]);
            if(a[j]=='\\')
            {
                e[s]='\0';
                siz=q->siz;
                for(k=0; k<q->siz; k++)
                {
                    if(strcmp(e, q->next[k]->str)==0)
                    {
                        q=q->next[k];
                        break;
                    }
                }
//                printf("%d %d\n", k, siz);
//                if(i==6)printf("%s %d %d\n", e, k, q);
                if(k>=siz)
                {
                    q->next[q->siz]=(p*)malloc(sizeof(p));
                    q->next[q->siz]->siz=0;
                    strcpy(q->next[q->siz]->str, e);
                    q->siz++;
                    q=q->next[siz];
                    q->od=1;
 //                   printf("%s",e);

                    s=0;
//                    printf("%s\n", e);

                }
                s=0;
            }
            else e[s++]=a[j];
        }
        if(!a[j] && a[j-1]!='\\')
        {
                    e[s]='\0';
                    siz=q->siz;
                    q->next[q->siz]=(p*)malloc(sizeof(p));
                    q->next[q->siz]->siz=0;
                    strcpy(q->next[q->siz]->str, e);
                    q->siz++;
                    q=q->next[siz];
                    q->od=0;
                    s=0;
//                    printf("%s\n", e);
        }
    }
//    cout<<123<<endl;
//    printf("root\n");
    pre(root);
    return 0;
}



### 关于遍历及其在PTA平台上的解法 #### 遍历概述 是一种重要的非线性数据结构,其节点之间具有层次关系。常见的遍历方法有三种:前序遍历、中序遍历和后序遍历[^1]。 - **前序遍历**:访问根节点,然后递归地进行左子的前序遍历,最后递归地进行右子的前序遍历- **中序遍历**:先递归地进行左子的中序遍历,再访问根节点,接着递归地进行右子的中序遍历- **后序遍历**:先递归地进行左子的后序遍历,再递归地进行右子的后序遍历,最后访问根节点。 这些遍历方式可以用于解决许多实际问题,比如表达式求值、二叉查找的操作等[^2]。 #### PTA平台上涉及遍历的经典题目解析 ##### 题目描述 假设有一道典型的PTA题目如下: > 给定一棵二叉的前序遍历序列和中序遍历序列,请重建该二叉并输出它的后序遍历序列。 这是一个经典的算法设计问题,通常可以通过治的思想来实现。 ##### 实现思路 通过析前序遍历和中序遍历的特点可知: - 前序遍历的第一个元素总是当前子的根节点。 - 中序遍历中,位于根节点左侧的部属于左子,右侧部则属于右子。 基于此特性,可以从给定的两个序列出发逐步构建完整的二叉,并最终得到所需的后序遍历结果[^3]。 ##### Python代码示例 以下是利用Python语言完成上述功能的一个简单例子: ```python class TreeNode: def __init__(self, value): self.val = value self.left = None self.right = None def build_tree(preorder, inorder): if not preorder or not inorder: return None root_val = preorder[0] root_index_inorder = inorder.index(root_val) node = TreeNode(root_val) # 构建左子 node.left = build_tree( preorder[1:root_index_inorder + 1], inorder[:root_index_inorder] ) # 构建右子 node.right = build_tree( preorder[root_index_inorder + 1:], inorder[root_index_inorder + 1:] ) return node def post_order_traversal(node, result=None): if result is None: result = [] if node is None: return post_order_traversal(node.left, result) post_order_traversal(node.right, result) result.append(node.val) return result # 测试用例 preorder_sequence = [&#39;a&#39;, &#39;b&#39;, &#39;d&#39;, &#39;e&#39;, &#39;c&#39;, &#39;f&#39;] inorder_sequence = [&#39;d&#39;, &#39;b&#39;, &#39;e&#39;, &#39;a&#39;, &#39;f&#39;, &#39;c&#39;] tree_root = build_tree(preorder_sequence, inorder_sequence) postorder_result = post_order_traversal(tree_root) print(postorder_result) # 输出应为[&#39;d&#39;, &#39;e&#39;, &#39;b&#39;, &#39;f&#39;, &#39;c&#39;, &#39;a&#39;] ``` 以上程序展示了如何依据指定条件创建一颗二叉以及获取对应的后续遍历顺序[^4]。 #### 总结 对于这种复杂的数据结构而言,掌握不同类型的遍历技巧是非常必要的。无论是理论学习还是实践应用,在面对诸如PTA这样的在线评测系统的挑战时,灵活运用所学知识能够有效提升解决问题的能力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值