bluecode-2024D-文件缓存系统

156 阅读3分钟

时间限制:C/C++ 1000MS,其他语言 2000MS
内存限制:C/C++ 128MB,其他语言 256MB
难度:中等

描述

请设计一个文件缓存系统,该文件缓存系统可以指定缓存的最大值(单位为字节)。

文件缓存系统有两种操作:存储文件(put)和读取文件(get) 操作命令为put fileName fileSize或者get fileName 

存储文件是把文件放入文件缓存系统中;读取文件是从文件缓存系统中访问已存在的文件,如果文件不存在,则不作任何操作。 

当缓存空间不足以存放新的文件时,根据规则删除文件,直到剩余空间满足新的文件大小为止,再存放新文件。 

具体的删除规则为:文件访问过后,会更新文件的最近访问时间和总的访问次数,当缓存不够时,按照第一优先顺序为访问次数从少到多,第二顺序为时间从老到新的方式来删除文件。

输入描述

第一行为缓存最大值m(整数,取值范围为0 < m <= 52428800) 

第二行为文件操作序列个数n(0 <= n <= 300000) 

从第三行起为文件操作序列,每个序列单独一行 

文件操作定义为"op fileName fileSize" fileName是文件名,fileSize是文件大小

输出描述

输出当前文件缓存中的文件名列表,文件名用英文逗号分隔,按字典顺序排序 

如:a,c 

如果文件缓存中没有文件,则输出NONE

用例输入 1 **

50
6
put a 10
put b 20
get a
get a
get b
put c 30

用例输出 1 **

a,c

提示

  1. 如果新文件的文件名和文件缓存中已有的文件名相同,则不会放在缓存中 

  2. 新的文件第一次存入到文件缓存中时,文件的总访问次数不会变化,文件的最近访问时间会更新到最新时间 

  3. 每次文件访问后,总访问次数加1,最近访问时间更新到最新时间 

  4. 任何两个文件的最近访问时间不会重复 

  5. 文件名不会为空,均为小写字母,最大长度为10 

  6. 缓存空间不足时,不能存放新文件 

  7. 每个文件大小都是大于0的整数

#include <iostream>
#include <unordered_map>
#include <set>
#include <vector>
#include <algorithm>
#include <string>

using namespace std;

struct FileInfo {
    string name;
    int size;
    int accessCount;
    long long lastAccessTime;
    
    FileInfo() : size(0), accessCount(0), lastAccessTime(0) {}  // Added default constructor
    FileInfo(string n, int s, long long t) : 
        name(n), size(s), accessCount(0), lastAccessTime(t) {}
};

class FileCache {
private:
    long long maxSize;  // Maximum cache size in bytes
    long long currentSize;  // Current occupied size
    long long timeStamp;  // For tracking access time
    unordered_map<string, FileInfo> cache;  // Main cache storage
    
    // For sorting files by access count and time
    struct Compare {
        bool operator()(const FileInfo& a, const FileInfo& b) const {
            if (a.accessCount != b.accessCount)
                return a.accessCount < b.accessCount;
            return a.lastAccessTime < b.lastAccessTime;
        }
    };

public:
    FileCache(long long m) : maxSize(m), currentSize(0), timeStamp(0) {}
    
    void put(string fileName, int fileSize) {
        // If file already exists, do nothing
        if (cache.find(fileName) != cache.end()) {
            return;
        }
        
        // While there's not enough space, remove files
        while (currentSize + fileSize > maxSize) {
            // Find file to remove
            set<FileInfo, Compare> sortedFiles;
            for (auto& pair : cache) {
                sortedFiles.insert(pair.second);
            }
            
            if (sortedFiles.empty()) break;
            
            // Remove file with lowest access count and oldest time
            auto toRemove = sortedFiles.begin();
            currentSize -= toRemove->size;
            cache.erase(toRemove->name);
        }
        
        // If there's enough space, add new file
        if (currentSize + fileSize <= maxSize) {
            cache[fileName] = FileInfo(fileName, fileSize, timeStamp++);
            currentSize += fileSize;
        }
    }
    
    void get(string fileName) {
        auto it = cache.find(fileName);
        if (it != cache.end()) {
            it->second.accessCount++;
            it->second.lastAccessTime = timeStamp++;
        }
    }
    
    void printCache() {
        if (cache.empty()) {
            cout << "NONE" << endl;
            return;
        }
        
        vector<string> files;
        for (auto& pair : cache) {
            files.push_back(pair.first);
        }
        sort(files.begin(), files.end());  // Sort alphabetically
        
        for (int i = 0; i < files.size(); i++) {
            cout << files[i];
            if (i < files.size() - 1) cout << ",";
        }
        cout << endl;
    }
};

int main() {
    long long m;
    int n;
    cin >> m >> n;
    
    FileCache cache(m);
    
    for (int i = 0; i < n; i++) {
        string op, fileName;
        int fileSize = 0;
        cin >> op >> fileName;
        if (op == "put") {
            cin >> fileSize;
            cache.put(fileName, fileSize);
        } else if (op == "get") {
            cache.get(fileName);
        }
    }
    
    cache.printCache();
    return 0;
}