week9作业题_A 咕咕东的目录管理器

A 咕咕东的目录管理器


题目描述

在这里插入图片描述
在这里插入图片描述

input:
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
output:
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

题目思路

这个题目是一个比较大,并且比较复杂的模拟题,其大致的要求是需要我们维护一个树形结构,然后就是一些对这个树形结构的一些操作。其中比较难的操作主要是TREE和UNDO操作。这就需要我们在执行完操作之后要记录下这些操作的相关信息。
在这个题目中我使用了三个数据结构,Node是数中的节点,包含节点名字name,以它为根的子树的节点个数Size,它的父亲节点fa,标记是否被访问tag;command是命令,dictionary是树,其中包含节点数组nd,当前目录crt,最后一个节点的索引last,记录命令的op数组。
实现方法:
MKDIR s:在当前目录新建一个节点并记录这个命令。
RM s:在当前目录下删除对应节点并记录命令。
CD s:分为两种情况考虑,s是…即返回上一级目录,如果当前目录不是根目录,则将当前目录改为它的父亲目录。否则改变cnt进入对应目录即可。
SZ:返回以当前目录为根的子树的目录个数。
LS:输出当前目录的子目录。
TREE:我们需要注意MKDIR和RM操作非常少,其他操作很多,这样节点数就远远小于TREE数,可能会有重复操作。这样我们就可以使用tag来记录是否被访问。
UNDO:从op中弹出一个命令,然后根据这个命令是MKDIR还是RM进行删除和插入的操作。

代码实现

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

#define _for(i,a,b) for(int i = (a); i < (b); i++)
#define _rep(i,a,b) for(int i = (a); i <= (b); i++)
struct Node{
	string name;
	int Size;
	int fa;
    map<string,int> mp;
    vector<string> pre,bck; 
	int tag;
};

struct command{
	string name;
	int pos;
	command(string n,int i){
		name=n;
		pos=i;
	}
};

class dictionary{
	private:
	Node nd[5010];
	int crt;
	int last;
vector<command> op;
public:
dictionary(){
    crt=0,last=1;
	nd[0].fa=-1;
	nd[0].name="root";
	nd[0].Size=1;
	nd[0].tag=0;
	nd[0].pre.clear();
	nd[0].bck.clear();
	nd[0].mp.clear();
	op.clear();
}
void update(int n){
	    int i=crt;
		while(i!=-1){
			nd[i].tag=0; 
			nd[i].Size+=n;
			i=nd[i].fa;
		}
}
void MKDIR(string s){
	if(nd[crt].mp.count(s)){
		cout<<"ERR"<<endl;
	}
	else{
		nd[crt].mp[s]=last;
	    nd[last].name=s;
	    nd[last].Size=1;
	    nd[last].fa=crt;
	    nd[last].mp.clear();
	    nd[last].pre.clear();
	    nd[last].bck.clear();
	    nd[last].tag=0;
		update(1);
		command cmd("MKDIR",last);
		op.push_back(cmd);
		last++;
		cout<<"OK"<<endl;
	}
}
void RM(string s){
	if(!nd[crt].mp.count(s))
	cout<<"ERR"<<endl;
	else{
		nd[crt].tag=0;
		int i=nd[crt].mp[s];
		int sz=nd[i].Size;
		nd[crt].mp.erase(s);
		update(-sz);
		command cmd("RM",i);
		op.push_back(cmd);
		cout<<"OK"<<endl;
	}
}
void CD(string s){
	if(s==".."){
		if(nd[crt].name=="root")
		cout<<"ERR"<<endl;
		else{
		command cmd("CD",crt);
		op.push_back(cmd);
		crt=nd[crt].fa;
		cout<<"OK"<<endl;
	}
}
	else{
		if(!nd[crt].mp.count(s))
		cout<<"ERR"<<endl;
		else{
		command cmd("CD",crt);
		op.push_back(cmd);
		int i=nd[crt].mp[s];
		crt=i;
		cout<<"OK"<<endl;
	}
	}
}
void SZ(){
	cout<<nd[crt].Size<<endl;
}
void LS(){
	if(nd[crt].mp.empty())
	cout<<"EMPTY"<<endl;
	else{
		if(nd[crt].mp.size()<=10){
			for(map<string,int>::iterator it=nd[crt].mp.begin();it!=nd[crt].mp.end();it++){
				cout<<it->first<<endl;
			}
		}
		else{
		map<string,int>::iterator it=nd[crt].mp.begin();
		_rep(i,1,5)
		{
			cout<<it->first<<endl;
			it++;
		}
		cout<<"..."<<endl;
		it=nd[crt].mp.end();
		_rep(i,1,5)
			it--;
		_rep(i,1,5)
		{
			cout<<it->first<<endl;
			it++;
		}
		}
	}
}
void pretrack(int id,int &cnt,vector<string> &pre){
	pre.push_back(nd[id].name);
	cnt--;
	if(cnt==0) return;
	for(map<string,int>::iterator it=nd[id].mp.begin(); it!=nd[id].mp.end(); it++){
		pretrack(it->second,cnt,pre);
		if(cnt==0) return;
	}
}
void bcktrack(int id,int &cnt,vector<string> &bck){	
   map<string,int>::iterator it=nd[id].mp.end(); 
	while(it!=nd[id].mp.begin())
	{
		it--;
		bcktrack(it->second,cnt,bck);
		if(cnt==0)	return;
	}
	bck.push_back(nd[id].name);
	cnt--;
}
void pushdown(int id){
	nd[id].pre.clear();
	nd[id].bck.clear();
	if(nd[id].Size<=10){
	int sze=nd[id].Size;
	pretrack(id,sze,nd[id].pre);
}
   else{
   	int cnt=5;
   	pretrack(id,cnt,nd[id].pre);
   	cnt=5;
   	bcktrack(id,cnt,nd[id].bck);
   }
   nd[id].tag=1;
}
void TREE(){
	if(!nd[crt].tag)	
		pushdown(crt);
	if(nd[crt].Size==1)	
		cout<<"EMPTY"<<endl;
	else {
	if(nd[crt].Size<=10) 
	{
		for(int i=0;i<nd[crt].pre.size();i++)
			cout<<nd[crt].pre[i]<<endl;
	}
	else
	{
		_for(i,0,5)
			cout<<nd[crt].pre[i]<<endl;
		cout<<"..."<<endl;
		for(int i=4;i>=0;i--)
			cout<<nd[crt].bck[i]<<endl;
	}
	} 
}
void UNDO(){
	if(op.empty())
	cout<<"ERR"<<endl;
	else{
		command cmd=op[op.size()-1];
		op.pop_back();
		if(cmd.name=="MKDIR")	
		{
		int i=cmd.pos;
		int sz=nd[i].Size;
		nd[crt].mp.erase(nd[i].name);
		update(-sz);
		}
		else if(cmd.name=="RM")
		{
			int i=cmd.pos;
			int sz=nd[i].Size;
			nd[crt].mp[nd[i].name]=i;
			int j=crt;
			while(j!=-1){
				nd[j].tag=0;
				nd[j].Size+=sz;;
				j=nd[j].fa;
			}
		}
		else
			crt=cmd.pos;
			cout<<"OK"<<endl;
	}
}
};
int main(){
	int T;
	cin>>T;
	_for(i,0,T)
	{
		int Q;
		cin>>Q;
		dictionary dic;
		_for(j,0,Q)
		{
			string cmd;
			cin>>cmd;
			if(cmd=="MKDIR")
			{
				string s;
				cin>>s;
				dic.MKDIR(s);
			}
			else if(cmd=="RM")
			{
				string s;
				cin>>s;
				dic.RM(s);
			}
			else if(cmd=="CD")
			{
				string s;
				cin>>s;
				dic.CD(s);
			}
			else if(cmd=="SZ")
				dic.SZ();
			else if(cmd=="LS")
				dic.LS();
			else if(cmd=="TREE")
				dic.TREE();
			else if(cmd=="UNDO")
				dic.UNDO();
		}
	 } 
	 return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值