带配额的文件系统 CSP 202012-3

带配额的文件系统 CSP 202012-3

由于学校的课程设计,需要我们写csp上面的题目,作为一名从来没有刷过算法题的小白,分享以下自己的解题思路,就当笔记了,使用python实现。因为学的是C语言的数据结构,没有学过python版的,可能很多地方不对,希望大家能够指出我的不足之处。

题目的大致意思就是我们要创建一个文件系统,用来管理文件,等于很简单的模拟了我们平时用过的文件系统。

结构

题目给了三种结构:

  1. 根目录
  2. 目录文件
  3. 普通文件

路径命名也和平时用的一样,例如:/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")

只会这么多了,情况肯定没考虑全,希望大佬指正

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值