A-目录管理器
题目描述:
解题思路:
这道题我觉得靠我们的更多是一个全局观,和一个分部份,和功能的能力,注意封装,也是代码能力的提升。
有些时候写东西最忌讳牵一发而动全身,如果我们分开去写的话,能增加可更改性还有更有可能分工合作
首先,可以将这个目录作为一棵树去维护。
然后就是对于指令的操作,将指令封装
再次就是一项一项实现功能
这里注意有一条是撤回上一步,那我们在每一次执行成功命令之后都要记录下来,当遇到撤回时,就可以利用起来了
#include<stdio.h>
#include<string.h>
#include<map>
#include<vector>
using namespace std;
char tmps[20];
struct Directory{
string name;
map<string, Directory*> children;
Directory* parent;
int subtreesize;
vector<string>* tenDescendants;
bool updated;
Directory(string name, Directory* parent)
{
this->name=name;
this->parent=parent;
this->subtreesize=1;
updated=true;
tenDescendants = new vector<string>;
}
public:
bool addChild(Directory* ch)
{
if(children.find(ch->name)!=children.end())
return false;
children[ch->name]=ch;
maintain(+ch->subtreesize);
return true;
}
Directory* getChild(string name)
{
auto it=children.find(name);
if(it==children.end())
return NULL;
return it->second;
}
Directory* mkdir(string name)
{
auto it=children.find(name);
if(it!=children.end()) return NULL;
Directory* ch=new Directory(name,this);
children[name]=ch;
maintain(+1);
return ch;
}
Directory* rm(string name)
{
map<string, Directory*>::iterator it=children.find(name);
if(it==children.end()) return NULL;
maintain(-1 * it->second->subtreesize);
children.erase(it);
return it->second;
}
Directory* cd(string name)
{
if(name=="..")
return this->parent;
return getChild(name);
}
void maintain(int delta)
{
updated=true;
subtreesize+=delta;
if(parent!=NULL)
parent->maintain(delta);
}
void sz()
{
printf("%d\n",this->subtreesize);
}
void ls()
{
int sz=children.size();
if(sz==0) printf("EMPTY\n");
else if(sz<=10){
for(auto &entry : children)
printf("%s\n",entry.first.c_str());
}
else{
auto it=children.begin();
for(int i=0;i<5;i++) printf("%s\n",it->first.c_str());
printf("...\n");
it=children.end();
for(int i=0;i<5;i++) it--;
for(int i=0;i<5;i++) printf("%s\n",it->first.c_str());
}
}
void tree()
{
if(subtreesize==1) printf("EMPTY\n");
else if(subtreesize<=10)
{
if(this->updated)
{
tenDescendants->clear();
treeAll(tenDescendants);
this->updated=false;
}
for(int i=0;i<subtreesize;i++) printf("%s\n",tenDescendants->at(i).c_str());
}
else
{
if(this->updated)
{
tenDescendants->clear();
treeFirstSome(5,tenDescendants);
treeLastSome(5,tenDescendants);
this->updated=false;
}
for(int i=0;i<5;i++) printf("%s\n",tenDescendants->at(i).c_str());
printf("...\n");
for(int i=9;i>=5;i--) printf("%s\n",tenDescendants->at(i).c_str());
}
}
private:
void treeAll(vector<string>* bar)
{
bar->push_back(name);
for(auto &entry : children)
entry.second->treeAll(bar);
}
void treeFirstSome(int num,vector<string>* bar)
{
bar->push_back(name);
if(--num==0) return;
int n=children.size();
auto it=children.begin();
while(n--)
{
int sts=it->second->subtreesize;
if(sts>=num)
{
it->second->treeFirstSome(num,bar);
return;
}
else
{
it->second->treeFirstSome(sts,bar);
num-=sts;
}
it++;
}
}
void treeLastSome(int num,vector<string>* bar)
{
int n=children.size();
auto it=children.end();
while(n--)
{
it--;
int sts=it->second->subtreesize;
if(sts>=num)
{
it->second->treeLastSome(num,bar);
return;
}
else
{
it->second->treeLastSome(sts,bar);
num-=sts;
}
}
bar->push_back(name);
}
};
struct Command{
const string CMD_NAMES[7]={"MKDIR","RM","CD","SZ","LS","TREE","UNDO"};
int type;
string arg;
Directory* tmpDir;
Command(string s)
{
//cout<<s<<endl;
for(int i=0;i<7;i++) if(s==CMD_NAMES[i]){
type=i;
if(type<3) scanf("%s",tmps),arg=tmps;
return;
}
}
};
void solve()
{
int n;
scanf("%d",&n);
Directory* now=new Directory("root",NULL);
vector<Command*> cmdlist;
while(n--)
{
scanf("%s",tmps);
Command* cmd=new Command(tmps);
//cout<<cmd->type<<endl;
switch(cmd->type)
{
case 0: case 1:{
cmd->tmpDir = cmd->type==0 ? now->mkdir(cmd->arg) : now->rm(cmd->arg);
if(cmd->tmpDir==NULL) printf("ERR\n");
else{
printf("OK\n");
cmdlist.push_back(cmd);
}
break;
}
case 2:{
Directory* ch=now->cd(cmd->arg);
if(ch==NULL) printf("ERR\n");
else{
printf("OK\n");
cmd->tmpDir=now;
now=ch;
cmdlist.push_back(cmd);
}
break;
}
case 3:{
now->sz();
break;
}
case 4:{
now->ls();
break;
}
case 5:{
now->tree();
break;
}
case 6:{
bool success=false;
while(!success&&!cmdlist.empty())
{
cmd=cmdlist.back();
cmdlist.pop_back();
switch(cmd->type)
{
case 0: success=now->rm(cmd->arg)!=NULL; break;
case 1: success=now->addChild(cmd->tmpDir); break;
case 2: now=cmd->tmpDir;success=true; break;
}
}
printf(success ? "OK\n" : "ERR\n");
}
}
}
}
int main(){
// freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
int t;
scanf("%d",&t);
while(t--) solve();
return 0;
}