带配额的文件系统 CSP 202012-3
由于学校的课程设计,需要我们写csp上面的题目,作为一名从来没有刷过算法题的小白,分享以下自己的解题思路,就当笔记了,使用python实现。因为学的是C语言的数据结构,没有学过python版的,可能很多地方不对,希望大家能够指出我的不足之处。
题目的大致意思就是我们要创建一个文件系统,用来管理文件,等于很简单的模拟了我们平时用过的文件系统。
结构
题目给了三种结构:
- 根目录
- 目录文件
- 普通文件
路径命名也和平时用的一样,例如:/A/B/1,根目录就是‘/’。
存储的方式很像树
其余不再赘述。
我使用了字典这个结构来存储每一个节点
要求
最后的要求,是需要我们实现三个操作
创建普通文件
这里需要明确,题目是默认了只能创建普通文件,而不能创建目录文件
大概列一下逻辑:
if 不超过限额:
if 存在:
if 是目录 或 替换后超限:
N
elif 是文件:
替换
Y
elif 不存在:
创建
if 创建成功:
Y
elif 要创建的目录与文件夹相同:
N
else:
N
C <file path> <file size>
删除文件
要记住:该指令始终认为能执行成功
这里要注意的是,删除节点后,还需要将空间大小还原
if 存在:
删除该节点及其后代节点
Y
R <file path>
设置配额
if 存在:
if 是目录文件 且 更改后不会不满足文件限额:
Y
N
Q <file path> <LD> <LR>
先上没考虑周全的代码
看了题目的实例1,以为题目默认了同一个文件名只用一次,没考虑到不同目录下可以出现相同文件名的情况,导致全错[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
所以拿了这分数,直接上代码
# -*- coding: utf-8 -*-
"""
'file name':(iscontent, [sons], father, size, LD, LR, nLD, nLR)
@author:咋了个办
"""
def isFit(path, size):
'''
判断是否超出限额
Parameters
----------
path : list
输入的路径列表.
size : int
文件大小.
Returns
-------
bool
如果路径不是目录,返回False,满足配额返回True,否则返回False.
'''
#先判断是否满足祖先的后代配额
for i in range(len(path) - 1):
#如果节点存在则判断是否满足,不存在则说明一定满足
if path[i] in dire:
t = dire[path[i]]
if not t[0] or (t[-3] != 0 and t[-1] + size > t[-3]):
return False
else:
return True
#再判断是否满足目录配额
t = dire[path[-2]]
if t[-4] != 0 and t[-2] + size > t[-4]:
return False
else:
return True
def delete(node):
'''
利用递归逐个删除节点,并且返回删除的节点总大小
Parameters
----------
node : char
要删除的节点.
Returns
-------
TYPE
当前节点的大小,如果是目录节点,则为0,如果是文件节点,则是文件的大小.
n : int
如果是文件节点,则为0,如果是目录节点,则为其后代节点的总大小.
'''
n = 0
t = dire[node]
if t[0]:
for i in range(len(t[1])):
n += sum(delete(t[1][i]))
return dire.pop(node)[3], n
def change(node, LR, LD):
'''
替换给定节点限额
Parameters
----------
node : char
要更换限额的节点.
LR : int
LR值.
LD : int
LD值.
Returns
-------
bool
如果更换成功,返回True,反之返回False.
'''
if node in dire:
t = dire[node]
if t[0]:
if (t[-1] <= LR or LR == 0) and (t[-2] <= LD or LD == 0):
t[-3], t[-4] = LR, LD
return True
return False
n = int(input())
dire = {'':[True, [], None, 0, 0, 0, 0, 0]}#先存储根节点
for _ in range(n):
s = input().split()
command = s[0]
path = s[1].split('/')
if command == 'C':
size = int(s[2])
if isFit(path, size):
#如果不超出限额
if path[-1] in dire:
#如果文件存在且是目录或者替换后超出限额
if dire[path[-1]][0] or not isFit(path, size - dire[path[-1]][3]):
print("N")
else:
#如果文件不是目录则替换
for i in range(len(path) - 1):
dire[path[i]][-1] += size - dire[path[-1]][3]
dire[path[-2]][-2] += size - dire[path[-1]][3]
dire[path[-1]] = [False, [], path[-2], size, 0, 0, 0, 0]
print("Y")
else:
#如果文件不存在,则逐个添加其目录
for i in range(len(path) - 1):
#如果目录存在,则增加大小,并添加儿子元素
if path[i] in dire:
dire[path[i]][-1] += size
dire[path[i]][1].extend(path[(i + 1):])
dire[path[i]][1] = list(set(dire[path[i]][1]))#去重
else:
#如果不存在直接添加目录
dire[path[i]] = [True, path[(i + 1):], path[i - 1], 0, 0, 0, 0, size]
dire[path[-2]][-2] += size
#最后添加文件
dire[path[-1]] = [False, [], path[-2], size, 0, 0, 0, 0]
print("Y")
else:
#超限或者路径上有文件则输出N
print("N")
elif command == 'R':
if path[-1] in dire:
#如果存在,则删除
x = delete(path[-1])
sums = sum(x)
for i in range(len(path) - 1):
t = dire[path[i]]
t[-1] -= sums
dire[path[-2]][-2] -= x[0]
print("Y")
elif command == 'Q':
LD = int(s[2])
LR = int(s[3])
if change(path[-1], LR, LD):
print("Y")
else:
print("N")
更改后
想法也很简单,就直接加上父亲节点作为key,直接上代码吧,拿到了30分
# -*- coding: utf-8 -*-
"""
'file name', 'father':(iscontent, [sons], father, size, LD, LR, nLD, nLR)
@author: 咋了个办
"""
def isFit(path, size):
'''
判断是否超出限额
Parameters
----------
path : list
输入的路径列表.
size : int
文件大小.
Returns
-------
bool
如果路径不是目录,返回False,满足配额返回True,否则返回False.
'''
#先判断是否满足祖先的后代配额
for i in range(len(path) - 1):
#如果节点存在则判断是否满足,不存在则说明一定满足
if path[i] == '' or (path[i], path[i - 1]) in dire:
if path[i] == '':
t = dire[(path[i], None)]
else:
t = dire[(path[i], path[i - 1])]
if not t[0] or (t[-3] != 0 and t[-1] + size > t[-3]):
return False
else:
return True
#再判断是否满足目录配额
if path[-2] == '':
t = dire[(path[-2], None)]
else:
t = dire[(path[-2], path[-3])]
if t[-4] != 0 and t[-2] + size > t[-4]:
return False
else:
return True
def delete(node):
'''
利用递归逐个删除节点,并且返回删除的节点总大小
Parameters
----------
node : char
要删除的节点.
Returns
-------
TYPE
当前节点的大小,如果是目录节点,则为0,如果是文件节点,则是文件的大小.
n : int
如果是文件节点,则为0,如果是目录节点,则为其后代节点的总大小.
'''
n = 0
t = dire[node]
if t[0]:
for i in range(len(t[1])):
if t[1][i] in dire:
n += sum(delete(t[1][i]))
return dire.pop(node)[3], n
def change(node, LR, LD):
'''
替换给定节点限额
Parameters
----------
node : char
要更换限额的节点.
LR : int
LR值.
LD : int
LD值.
Returns
-------
bool
如果更换成功,返回True,反之返回False.
'''
if node in dire:
t = dire[node]
if t[0]:
if (t[-1] <= LR or LR == 0) and (t[-2] <= LD or LD == 0):
t[-3], t[-4] = LR, LD
return True
return False
n = int(input())
dire = {('',None):[True, [], None, 0, 0, 0, 0, 0]}#先存储根节点
for _ in range(n):
s = input().split()
command = s[0]
path = s[1].split('/')
if command == 'C':
size = int(s[2])
if isFit(path, size):
#如果不超出限额
if (path[-1], path[-2]) in dire:
#如果文件存在且是目录或者替换后超出限额
if dire[(path[-1], path[-2])][0] or not isFit(path, size - dire[(path[-1], path[-2])][3]):
print("N")
else:
#如果文件不是目录则替换
dire[(path[0], None)][-1] += size - dire[(path[-1], path[-2])][3]
for i in range(1, len(path) - 1):
dire[(path[i], path[i-1])][-1] += size - dire[(path[-1], path[-2])][3]
if path[-2] == '':
t = dire[(path[-2], None)]
else:
t = dire[(path[-2], path[-3])]
t[-2] += size - dire[(path[-1], path[-2])][3]
dire[(path[-1], path[-2])] = [False, [], path[-2], size, 0, 0, 0, 0]
print("Y")
else:
#如果文件不存在,则逐个添加其目录
temp = []
dire[(path[0], None)][-1] += size
for i in range(1, len(path)):
temp.append((path[i], path[i - 1]))
dire[(path[0], None)][1].extend(temp)
dire[(path[0], None)][1] = list(set(dire[(path[0], None)][1]))
for i in range(1, len(path) - 1):
#如果目录存在,则增加大小,并添加儿子元素
temp = []
for j in range(i + 1, len(path)):
temp.append((path[j], path[j - 1]))
if (path[i], path[i-1]) in dire:
dire[(path[i], path[i-1])][-1] += size
dire[(path[i], path[i-1])][1].extend(temp)
dire[(path[i], path[i-1])][1] = list(set(dire[(path[i], path[i-1])][1]))#去重
else:
#如果不存在直接添加目录
dire[(path[i], path[i-1])] = [True, temp, path[i - 1], 0, 0, 0, 0, size]
dire[(path[-2], path[-3])][-2] += size
#最后添加文件
dire[(path[-1], path[-2])] = [False, [], path[-2], size, 0, 0, 0, 0]
print("Y")
else:
#超限或者路径上有文件则输出N
print("N")
elif command == 'R':
if (path[-1], path[-2]) in dire:
#如果存在,则删除
x = delete((path[-1], path[-2]))
sums = sum(x)
for i in range(len(path) - 1):
if path[i] == '':
t = dire[(path[i], None)]
else:
t = dire[(path[i], path[i - 1])]
t[-1] -= sums
if path[-2] == '':
t = dire[(path[-2], None)]
else:
t = dire[(path[-2], path[-3])]
t[-2] -= x[0]
print("Y")
elif command == 'Q':
LD = int(s[2])
LR = int(s[3])
if path[-1] == '':
t = (path[-1], None)
else:
t = (path[-1], path[-2])
if change(t , LR, LD):
print("Y")
else:
print("N")
只会这么多了,情况肯定没考虑全,希望大佬指正