Week9 作业 A - 咕咕东的目录管理器

2023-05-16

题面
咕咕东的雪梨电脑的操作系统在上个月受到宇宙射线的影响,时不时发生故障,他受不了了,想要写一个高效易用零bug的操作系统 —— 这工程量太大了,所以他定了一个小目标,从实现一个目录管理器开始。前些日子,东东的电脑终于因为过度收到宇宙射线的影响而宕机,无法写代码。他的好友TT正忙着在B站看猫片,另一位好友瑞神正忙着打守望先锋。现在只有你能帮助东东!
初始时,咕咕东的硬盘是空的,命令行的当前目录为根目录 root。
目录管理器可以理解为要维护一棵有根树结构,每个目录的儿子必须保持字典序。

现在咕咕东可以在命令行下执行以下表格中描述的命令:
命令
类型
实现
说明
MKDIR s
操作
在当前目录下创建一个子目录 s,s 是一个字符串
创建成功输出 “OK”;若当前目录下已有该子目录则输出 “ERR”
RM s
操作
在当前目录下删除子目录 s,s 是一个字符串
删除成功输出 “OK”;若当前目录下该子目录不存在则输出 “ERR”
CD s
操作
进入一个子目录 s,s 是一个字符串(执行后,当前目录可能会改变)
进入成功输出 “OK”;若当前目录下该子目录不存在则输出 “ERR”
特殊地,若 s 等于 “…” 则表示返回上级目录,同理,返回成功输出 “OK”,返回失败(当前目录已是根目录没有上级目录)则输出 “ERR”
SZ
询问
输出当前目录的大小
也即输出 1+当前目录的子目录数
LS
询问
输出多行表示当前目录的 “直接子目录” 名
若没有子目录,则输出 “EMPTY”;若子目录数属于 [1,10] 则全部输出;若子目录数大于 10,则输出前 5 个,再输出一行 “…”,输出后 5 个。
TREE
询问
输出多行表示以当前目录为根的子树的前序遍历结果
若没有后代目录,则输出 “EMPTY”;若后代目录数+1(当前目录)属于 [1,10] 则全部输出;若后代目录数+1(当前目录)大于 10,则输出前 5 个,再输出一行 “…”,输出后 5 个。若目录结构如上图,当前目录为 “root” 执行结果如下,
UNDO
特殊
撤销操作
撤销最近一个 “成功执行” 的操作(即MKDIR或RM或CD)的影响,撤销成功输出 “OK” 失败或者没有操作用于撤销则输出 “ERR”
输入
输入文件包含多组测试数据,第一行输入一个整数表示测试数据的组数 T (T <= 20);
每组测试数据的第一行输入一个整数表示该组测试数据的命令总数 Q (Q <= 1e5);
每组测试数据的 2 ~ Q+1 行为具体的操作 (MKDIR、RM 操作总数不超过 5000);
面对数据范围你要思考的是他们代表的 “命令” 执行的最大可接受复杂度,只有这样你才能知道你需要设计的是怎样复杂度的系统。
输出
每组测试数据的输出结果间需要输出一行空行。注意大小写敏感。
时空限制
Time limit 6000 ms
Memory limit 1048576 kB
样例输入
1
22
MKDIR dira
CD dirb
CD dira
MKDIR a
MKDIR b
MKDIR c
CD …
MKDIR dirb
CD dirb
MKDIR x
CD …
MKDIR dirc
CD dirc
MKDIR y
CD …
SZ
LS
TREE
RM dira
TREE
UNDO
TREE
样例输出
OK
ERR
OK
OK
OK
OK
OK
OK
OK
OK
OK
OK
OK
OK
OK
9
dira
dirb
dirc
root
dira
a
b
c
dirb
x
dirc
y
OK
root
dirb
x
dirc
y
OK
root
dira
a
b
c
dirb
x
dirc
y
解题思路:
首先对每条指令,每个指令有指令的类型以及MKDIR,RM,CD三个指令还有参数,所以用Command结构体进行封装。又因为目录管理器是一棵目录树的数据结构,所以需要维护该树,又因为要求字典序,所以要用map<string,目录>,它可以根据key也就是string 在内部进行排序,用类Directory表示。
具体指令:
MKDIR 查找目标目录,存在则输出 “ERR”,创建目录,往map里插入,成功输出 “OK”;往前调用函数更改 snum值
RM 查找目标目录,不存在则输出 “ERR”,删除成功输出 “OK”;记录命令
CD 查找目标目录,不存在则输出 “ERR”,否则更改workdir 记录命令
SZ 直接返回 workdir->snum
LS 若没有子目录,则输出 “EMPTY”;若子目录数属于 [1,10] 则全部输出;若子目录数大于 10,则前序输出前 5 个,再输出一行 “…”,后序输出后 5 个。
TREE 若没有后代目录,则输出 “EMPTY” ,若后代目录数+1(当前目录)属于 [1,10] 则全部前序输出,若后代目录数+1(当前目录)大于 10,则前序输出前 5 个,后序遍历后5个 加上缓存
UNDO 取出满足条件的最后一条命令,还原。mk->rm rm->mk,注意的是取出原先删除的结点 cd->直接还原工作目录

#include<iostream>
#include<vector>
#include<cstring>
#include<map>
using namespace std;

struct ptrcmp {
    bool operator()(const char* s1, const char* s2) const {
        return strcmp(s1, s2) < 0;
    }
};

struct dirnode {
    char * name;
    dirnode* up;
    map<char *, dirnode*,ptrcmp> sub;
    int snum;
    vector<char*> qianxu;
    vector<char*> houxu;
    int updated;
    dirnode(dirnode* up, char * name) :up(up), name(name) {
        snum = 1;
        updated = 1;
    }
};

struct opcode {
    char * name;
    int optype;
    dirnode* olddir;
    opcode(char * name, int optype) :name(name), optype(optype) {
        olddir = NULL;
    }
    opcode(char * name, int optype, dirnode* olddir) :name(name), optype(optype), olddir(olddir) {}
};

class dir {
public:
    dir() {
        char* root = new char[10];
        strcpy(root, "root");
        workdir = new dirnode(NULL, root);
        rmdir = NULL;
    }
    void touched(int num) {
        dirnode* thisnode = workdir;
        while (thisnode != NULL) {
            thisnode->snum += num;
            thisnode->updated = 1;
            thisnode = thisnode->up;
        }
    }
    void mkdir(char * s) {
        map<char *, dirnode*,ptrcmp>::iterator it = workdir->sub.find(s);
        if (it != workdir->sub.end()) {
            printf("ERR\n");
            return;
        }
        dirnode* newnode = new dirnode(workdir, s);
        workdir->sub.insert(make_pair(s, newnode));
        history.push_back(opcode(s, 1));
        touched(1);
        printf("OK\n");
        return;
    }
    void rm(char * s) {
        map<char *, dirnode*,ptrcmp>::iterator it = workdir->sub.find(s);
        if (it == workdir->sub.end()) {
            printf("ERR\n");
            return;
        }
        rmdir = it->second;
        workdir->sub.erase(it);
        history.push_back(opcode(s, 2, rmdir));
        touched(0-rmdir->snum);
        printf("OK\n");
        return;
    }
    void cd(char * s) {
        if (s[0] == '.' && s[1] == '.' && s[2] == '\0') {
            if (workdir->up == NULL) {
                printf("ERR\n");
                return;
            }
            history.push_back(opcode(s, 3, workdir));
            workdir = workdir->up;
            printf("OK\n");
            return;
        }
        map<char *, dirnode*,ptrcmp>::iterator it = workdir->sub.find(s);
        if (it == workdir->sub.end()) {
            printf("ERR\n");
            return;
        }
        history.push_back(opcode(s, 3, workdir));
        workdir = it->second;
        printf("OK\n");
        return;
    }
    int sz() {
        return workdir->snum;
    }
    void ls() {
        if (workdir->sub.empty()) {
            printf("EMPTY\n");
            return;
        }
        if (workdir->sub.size() <= 10) {
            for (auto it = workdir->sub.begin(); it != workdir->sub.end(); it++) {
                printf("%s\n", it->first);
            }
            return;
        }
        int count = 1;
        for (auto it = workdir->sub.begin(); it != workdir->sub.end(); it++) {
            printf("%s\n", it->first);
            if (count == 5) {
                printf("...\n");
                break;
            }
            count++;
        }
        count = 1;
        vector<char*> toput;
        for (auto it = workdir->sub.rbegin(); it != workdir->sub.rend(); it++) {
            toput.push_back(it->first);
            if (count == 5) {
                break;
            }
            count++;
        }
        for (int i = 4; i >= 0; i--) {
            printf("%s\n", toput[i]);
        }
        toput.clear();
        return;
    }
    void undo() {
        if (history.empty()) {
            printf("ERR\n");
            return;
        }
        opcode* ccode = &history.back();
        if (ccode->optype == 1) { //mk->rm
            map<char *, dirnode*,ptrcmp>::iterator it = workdir->sub.find(ccode->name);
            workdir->sub.erase(it);
            history.pop_back();
            touched(-1);
            printf("OK\n");
            return;
        }
        else if (ccode->optype == 2) { //rm->mk
            map<char *, dirnode*,ptrcmp>::iterator it = workdir->sub.find(ccode->name);
            workdir->sub.insert(make_pair(ccode->name, ccode->olddir));
            history.pop_back();
            touched(ccode->olddir->snum);
            printf("OK\n");
            return;
        }
        else if (ccode->optype == 3) { //cd
            workdir = ccode->olddir;
            history.pop_back();
            printf("OK\n");
            return;
        }
        history.pop_back();
        printf("ERR\n");
    }
    void tree() {
        if (workdir->sub.empty()) {
            printf("EMPTY\n");
            return;
        }
        if (sz() <= 10) {
            if (workdir->updated) {
                workdir->qianxu.clear();
                preorderall(workdir,&workdir->qianxu);
                workdir->updated = 0;
            }
            for (int i = 0; i < workdir->qianxu.size(); i++) {
                printf("%s\n", workdir->qianxu[i]);
            }
            return;
        }
        if (workdir->updated) {
            workdir->qianxu.clear();
            workdir->houxu.clear();
            int count = 5;
            preorder(workdir, count, &workdir->qianxu);
            count = 5;
            postorder(workdir, count,&workdir->houxu);
            workdir->updated = 0;
        }
        for (int i = 0; i < 5; i++) {
            printf("%s\n", workdir->qianxu[i]);
        }
        printf("...\n");
        for (int i = 4; i >= 0; i--) {
            printf("%s\n", workdir->houxu[i]);
        }
    }

    void preorderall(dirnode* cnode, vector<char*>* qianxu) {
        qianxu->push_back(cnode->name);
        for (auto it = cnode->sub.begin(); it != cnode->sub.end(); it++) {
            preorderall(it->second,qianxu);
        }
    }
    void preorder(dirnode* cnode, int& remain,vector<char*>* qianxu) {
        if (remain < 1) return;
        qianxu->push_back(cnode->name);
        remain--;
        for (auto it = cnode->sub.begin(); it != cnode->sub.end() && remain > 0; it++) {
            preorder(it->second, remain,qianxu);
        }
    }
    void postorder(dirnode* cnode, int& remain, vector<char*>* houxu) {
        for (auto it = cnode->sub.rbegin(); it != cnode->sub.rend() && remain > 0; it++) {
            postorder(it->second, remain,houxu);
        }
        if (remain < 1) return;
        houxu->push_back(cnode->name);
        remain--;
    }

private:
    dirnode* workdir;
    dirnode* rmdir;
    vector<opcode> history;
};

void mainloop() {
    int q;
    scanf("%d", &q);
    dir d;
    char op[8];
    char * s;
    for (int qi = 0; qi < q; qi++) {
        scanf("%s", op);
        if (op[0] == 'M') {
            s = new char[24];
            scanf("%s", s);
            d.mkdir(s);
        }
        else if (op[0] == 'R') {
            s = new char[24];
            scanf("%s", s);
            d.rm(s);
        }
        else if (op[0] == 'C') {
            s = new char[24];
            scanf("%s", s);
            d.cd(s);
        }
        else if (op[0] == 'S') {
            printf("%d\n", d.sz());
        }
        else if (op[0] == 'L') {
            d.ls();
        }
        else if (op[0] == 'T') {
            d.tree();
        }
        else if (op[0] == 'U') {
            d.undo();
        }
    }

}
int main()
{
    int t;
    scanf("%d", &t);
    for (int ti = 0; ti < t; ti++) {
        mainloop();
        if (ti != t - 1) {
            printf("\n");
        }
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Week9 作业 A - 咕咕东的目录管理器 的相关文章

  • luogu P2078 朋友 基础并查集 联通块的个数

    题目背景 小明在A公司工作 xff0c 小红在B公司工作 题目描述 这两个公司的员工有一个特点 xff1a 一个公司的员工都是同性 A公司有N名员工 xff0c 其中有P对朋友关系 B公司有M名员工 xff0c 其中有Q对朋友关系 朋友的朋
  • ubuntu focal InRelease 没有数字签名 解决办法

    E 无法下载 http ppa launchpad net morphis anbox support ubuntu dists focal InRelease 403 Forbidden IP 185 125 190 52 80 E 仓库
  • Qt笔记---QMenu添加自定义菜单

    Qt笔记 QMenu添加自定义菜单 QMenu用于显示菜单栏交互 xff0c 使用QAction作为选项添加 xff0c 生成的菜单栏为默认样式 默认样式 xff1a 想要在菜单栏上显示一些其他的部件组成的选项 xff0c 可以使用QMen
  • 怎样关闭ubuntu 鼠标悬停自动点击

    终端运行 mousetweaks s
  • 将C盘虚拟机迁移到D盘

    之前没有注意把虚拟机创建在了C盘 xff0c 现在C盘空间不足 xff0c 需要迁移到D盘 首先需要关闭CentOS16虚拟机 xff0c 关闭之后 xff0c 复制整个虚拟机文件夹 把CentOS16复制到D盘这个目录下 xff1a 打开
  • VS2019 + CUDA11.0开发环境配置

    VS2019 43 CUDA11 0开发环境配置 确认系统是否支持安装VS2019安装CUDA11 0实例程序 确认系统是否支持 确认自己的设备是否支持CUDA11 0 打开NVIDIA控制面板 xff0c 一般N卡的设备都在鼠标右键就有
  • 排序算法:选择排序

    1 什么是选择排序 xff1f xff08 摘抄自百度百科 xff09 选择排序 xff08 Selection sort xff09 是一种简单直观的排序算法 它的工作原理是 xff1a 第一次从待排序的数据元素中选出最小 xff08 或
  • markdown-it 介绍,以及使用,自定义规则

    markdown it markdown it 是前端的一个 markdown 解析库 xff0c 将 markdown 解析成 Token 流 网上都有很多详细的 token 流解析过程 xff0c 请先简单看一遍 markdown it
  • apt-get update 报错

    sudo apt get update 报错 E 无法解析软件包文件 var lib apt lists ppa launchpad net rabbitvcs ppa ubuntu dists xenial main i18n Trans
  • Tiny210裸机开发初体验

    从昨天开始搞了一下Tiny210的裸机 xff0c 长时间没玩有点生疏了 由于开发板光盘自带裸机程序例程 xff0c 所以先跑一下简单的点灯 xff0c 打通调试通路然后再进行学习 首先使用了方法1 xff1a 参考国嵌视频烧录superb
  • System Verilog——C语言调用SV对象中的方法

    本文接上一篇文章 xff0c 即调用System Verilog 任务的C 任务 xff0c 简介如下 https blog csdn net qq 31348733 article details 101000399 如何在C语言中调用S
  • 程序设计思维与实践 Week15 作业

    ZJM 与纸条 ZJM 的女朋友是一个书法家 xff0c 喜欢写一些好看的英文书法 有一天 ZJM 拿到了她写的纸条 xff0c 纸条上的字暗示了 ZJM 的女朋友 想给 ZJM 送生日礼物 ZJM 想知道自己收到的礼物是不是就是她送的 x
  • 利用Python的scrapy框架爬取手游排行前几名的手游信息

    初学scrapy框架 Scrapy是一个为了爬取网站数据 xff0c 提取结构性数据而编写的应用框架 可以应用在包括数据挖掘 xff0c 信息处理或存储历史数据等一系列的程序中 有关于scrapy的教学与基础知识这里不做解释 xff0c 感
  • 【ORB-SLAM3】CMake Error at CMakeLists.txt:37 (message): OpenCV > 2.4.3 not found.

    项目场景 xff1a ZED2相机配置使用ORB SLAM3 ZED2相机配置使用ORB SLAM3 xff0c 出现关于opencv的报错 问题描述 CMake Error at CMakeLists txt 37 message Ope
  • 领航-跟随型编队 (六)避障问题综述

    领航 跟随型编队避障问题指编队在运动过程中 xff0c 领航机器人根据某种方式获取与识别前方障碍物 xff0c 同时编队整体采取一定方法及时规避障碍物与防止内部碰撞 xff0c 涉及到障碍物检测 编队避障规划 编队避碰协调 xff0c 运动
  • 领航跟随型编队(十)编队实验视频

    实验一 xff1a 圆形轨迹下编队生成与保持实验 如图 5 19 所示 xff0c 两个机器人完成从随机状态形成编队并沿圆形轨迹保持编队运行 xff0c 且图中下方的窗口动态显示编队的运行情况 领航机器人初始信息 xff1a 坐标 0 5m
  • 内网项目中引入NoVnc服务

    内网项目中引入NoVnc服务 背景目标方案部署步骤完成后验证效果 背景 目前项目中 xff0c 管理的实例底层为虚拟机 xff0c 而在用户或运维人员管理具体的实例时 xff0c 需另外启动VNC Viewer客户端才能配置实例 xff0c
  • Jupyter最全指南及常见问题(持续更新)

    anaconda与jupyter lab搭配使用 jupyter lab是jupyter notebook升级版 非常好用 命令行安装 xff1a pip install jupyterlab即可 安装好了之后 xff0c 命令行输入 ju
  • 头文件

    include lt iostream gt include lt algorithm gt include lt cassert gt include lt string gt include lt sstream gt include
  • MySQL 8.0 密码重置

    MySQL 版本 8 0 系统 xff1a Linux 原因 xff1a 数据库无法登录 xff08 非忘记密码 xff09 xff0c 登上后发现竟然数据库被黑了 xff0c 留了一条 BTC 的 赎回记录 首先关闭现有的mysql 服务

随机推荐

  • MySQL 取出每个分组中最新的一条数据(ID最大)

    场景 xff1a 由于一个摄像头管理一个范围 xff0c 且管理的某个人可以多次犯规 故 xff0c 一个摄像头可以上报有多个事件 xff0c 多个事件可能同时上报 xff0c 可能有先后顺序 需求 xff1a 现地图只显示有事件摄像头的最
  • java获取天气接口

    如下图 span class token keyword package span span class token namespace com span class token punctuation span octv span cla
  • Eclipse反编译插件(免费无需下载资源)

    分享一个适用eclipse的java反编译插件JD Decompiler 最近eclipse插件库被玩坏了 xff0c 于是重新安装插件 xff0c 站内搜索发现反编译插件竟然都要积分下载了 以下是插件官网 xff0c 看不懂英文的小伙伴用
  • JAVA基础疑难——001Boolean类型传值问题

    今天在帮助一位小伙伴解决传值的问题的时候 xff0c 发现他使用的是boolean类型的带参方法 程序执行没有问题 xff0c 但是boolen类型的值传不出来 怎么找问题都找不出来 今天就该问题所产生的原因给大家分享一下 xff0c 下面
  • 洛谷p4180 ac自动机

    匹配字符串时 xff0c 对于重复的单词我们只考虑一次 xff0c 我们开一个数组记录 xff0c 重复单词的第一个id将重复单词的出现次数全部变为第一次出现的个数相加 且在匹配时 xff0c 对于每个now只扫描一次 xff0c 不重复扫
  • Debian开启SSH

    一 Debian开启SSH 参考链接 xff1a https blog csdn net zzpzheng article details 71170572 https help aliyun com knowledge detail 41
  • IDEA配置Tomcat

    IntelliJ IDEA 2017 配置Tomcat 运行Web项目 以前都用MyEclipse写程序的 突然用了IDEA各种不习惯的说 借鉴了很多网上好的配置办法 xff0c 感谢各位大神 前期准备 IDEA JDK Tomcat请先在
  • 如何实现页面登录验证

    现在很多网站在登录的时候都需要输入验证码 xff0c 现在输入的验证码方式层出不穷有单单是数字的 字母 xff08 又分大小写 xff09 的 xff0c 有数字 字母混合的 xff0c 有给出运算表达式需要回答结果的 xff0c 还有的卡
  • REST,RESTful到底是个什么?

    0 REST不是 34 rest 34 这个单词 而是几个单词缩写 但即使那几个单词说出来 也无法理解在说什么 不是要贬低人 是我自己也理解困难 1 REST描述的是在网络中client和server的一种交互形式 REST本身不实用 实用
  • spring boot 入门

    什么是 spring boot Spring Boot是由Pivotal团队提供的全新框架 xff0c 其设计目的是用来简化新Spring应用的初始搭建以及开发过程 该框架使用了特定的方式来进行配置 xff0c 从而使开发人员不再需要定义样
  • html如何使用springboot进行跳转

    问题 xff1a 页面之间的跳转 xff0c 通常带有值的传输 xff0c 但是 xff0c 在现在比较流行的SPRING MVC WEB 开发模型中 xff0c 设计机制导致页面之间的直接接跳转和传值不被支持 xff08 网上看到的 xf
  • PowerShell升级

    PowerShell升级 1 查看版本 span class token variable PSVersionTable span 2 搜索软件包 winget search Microsoft PowerShell 3 使用 id 参数安
  • 四子棋对决(一)

    1 算法一 cc Class extends cc Component properties overLab default null type cc Label chessPrefab 棋子的预制资源 default null type
  • 四子棋对决(二)

    import com from 39 common 39 cc Class extends cc Component properties overLab default null type cc Label chessPrefab 棋子的
  • 四子棋对决(三)

    客户端 开始场景 xff1a menuScript js import global from 39 global 39 var com 61 require 39 common 39 cc Class extends cc Compone
  • centos 7怎么通过图形界面来配置静态ip

    除了通过修改配置文件的方法来配置静态ip 我们还可以通过图形界面来配置 xff0c 这样做其实更加方便一点 1 先点击应用程序 xff0c 点击系统工具 xff0c 点击设置 2 选择网络 3 打开网络 xff0c 点击设置 4 选择ipv
  • JavaScript

    JavaScript 一 JavaScript输入输出语句 JavaScript提供了一些输入输出语句 xff1a 方法说明归属alert msg 浏览器弹出警示框浏览器console msg 浏览器控制台输出信息浏览器prompt inf
  • th tr td区别

    tr定义行 th表示头部 td表示单元格 tr不能单独存在 xff0c 相当于table的属性标签 xff0c 而th td也应当放在tr中 lt th gt 不光是粗体 xff0c 还是居中的 lt DOCTYPE html gt lt
  • --12月月赛题解--

    12月月赛题解 问题 A 求区间最大值 题目描述 给你一个长度为n的序列 a 1 a 2 a n 下标从1到n Q个询问 每次询问给出一个L和R 你需要输出最大的a i L lt 61 i lt 61 R 输入 单组数据 第一行给出n n
  • Week9 作业 A - 咕咕东的目录管理器

    题面 咕咕东的雪梨电脑的操作系统在上个月受到宇宙射线的影响 xff0c 时不时发生故障 xff0c 他受不了了 xff0c 想要写一个高效易用零bug的操作系统 这工程量太大了 xff0c 所以他定了一个小目标 xff0c 从实现一个目录管