Design data structures and algorithms for inmemory file system (original) (raw)

Last Updated : 16 Feb, 2026

Explain the data structures and algorithms that you would use to design an in-memory file system. Illustrate with an example in the code logic where possible.

**Asked In: Amazon

A file system, in its most simplistic version, consists of Files and Directories. Each Directory contains a set of Files and Directories. Since Files and Directories share so many characteristics, we've implemented them such that they inherit from the same class, Entry.

**Implemented Main logic in Java

C++ `

#include #include #include #include

// Entry is superclass for both File and Directory class Entry { protected: Entry* parent; long created; long lastUpdated; long lastAccessed; std::string name;

public: Entry(std::string n, Entry* p) { name = n; parent = p; created = lastUpdated = lastAccessed = std::time(nullptr); }

bool deleteEntry() {
    if (parent == nullptr)
        return false;
    return parent->deleteEntry(this);
}

virtual int size() = 0;

// Getters and setters
long getCreationTime() {
    return created;
}

long getLastUpdatedTime() {
    return lastUpdated;
}

long getLastAccessedTime() {
    return lastAccessed;
}

void changeName(std::string n) {
    name = n;
}

std::string getName() {
    return name;
}

};

// A class to represent a File (Inherits from Entry) class File : public Entry { private: std::string content; int size;

public: File(std::string n, Entry* p, int sz) : Entry(n, p) { size = sz; }

int size() override {
    return size;
}

std::string getContents() {
    return content;
}

void setContents(std::string c) {
    content = c;
}

};

// A class to represent a Directory (Inherits from Entry) class Directory : public Entry { private: std::vector<Entry*> contents;

public: Directory(std::string n, Entry* p) : Entry(n, p) {}

int size() override {
    int size = 0;
    for (Entry* e : contents)
        size += e->size();
    return size;
}

int numberOfFiles() {
    int count = 0;
    for (Entry* e : contents) {
        if (dynamic_cast<Directory*>(e)) {
            count++; // Directory counts as a file
            Directory* d = dynamic_cast<Directory*>(e);
            count += d->numberOfFiles();
        } else if (dynamic_cast<File*>(e))
            count++;
    }
    return count;
}

bool deleteEntry(Entry* entry) {
    return contents.erase(std::remove(contents.begin(), contents.end(), entry), contents.end()) > contents.end();
}

void addEntry(Entry* entry) {
    contents.push_back(entry);
}

std::vector<Entry*> getContents() {
    return contents;
}

};

int main() { Directory root("root", nullptr);

File file1("file1.txt", &root, 100);
File file2("file2.txt", &root, 200);

root.addEntry(&file1);
root.addEntry(&file2);

std::cout << "Total size: " << root.size() << std::endl;
std::cout << "Total files: " << root.numberOfFiles() << std::endl;

return 0;

}

Java

import java.util.ArrayList;

// Entry is superclass for both File and Directory abstract class Entry { protected Directory parent; protected long created; protected long lastUpdated; protected long lastAccessed; protected String name;

public Entry(String n, Directory p)
{
    name = n;
    parent = p;
    created = System.currentTimeMillis();
    lastUpdated = System.currentTimeMillis();
    lastAccessed = System.currentTimeMillis();
}

public boolean delete()
{
    if (parent == null)
        return false;
    return parent.deleteEntry(this);
}

public abstract int size();

/* Getters and setters. */
public long getcreationTime()
{
    return created;
}

public long getLastUpdatedTime()
{
    return lastUpdated;
}

public long getLastAccessedTime()
{
    return lastAccessed;
}

public void changeName(String n)
{
    name = n;
}

public String getName()
{
    return name;
}

}

// A class to represent a File (Inherits from Entry) class File extends Entry { private String content; private int size;

public File(String n, Directory p, int sz)
{
    super(n, p);
    size = sz;
}

public int size()
{
    return size;
}

public String getContents()
{
    return content;
}

public void setContents(String c)
{
    content = c;
}

}

// A class to represent a Directory (Inherits from Entry) class Directory extends Entry { protected ArrayList contents; // Fixed Arraylist → ArrayList

public Directory(String n, Directory p)
{
    super(n, p);
    contents = new ArrayList<Entry>();  // Fixed Arraylist → ArrayList
}

public int size()
{
    int size = 0;
    for (Entry e : contents)
        size += e.size();

    return size;
}

public int numberOfFiles()
{
    int count = 0;
    for (Entry e : contents)
    {
        if (e instanceof Directory)
        {
            count++; // Directory counts as a file
            Directory d = (Directory) e;
            count += d.numberOfFiles();   // Fixed spacing typo
        }
        else if (e instanceof File)
            count++;
    }
    return count;
}

public boolean deleteEntry(Entry entry)
{
    return contents.remove(entry);
}

public void addEntry(Entry entry)
{
    contents.add(entry);
}

protected ArrayList<Entry> getContents()
{
    return contents;
}

} public class GFG { public static void main(String[] args) { Directory root = new Directory("root", null);

    File file1 = new File("file1.txt", root, 100);
    File file2 = new File("file2.txt", root, 200);

    root.addEntry(file1);
    root.addEntry(file2);

    System.out.println("Total size: " + root.size());
    System.out.println("Total files: " + root.numberOfFiles());
}

}

Python

import time from typing import List

Entry is superclass for both File and Directory

class Entry: def init(self, n: str, p: 'Entry' = None): self.parent = p self.created = time.time() self.lastUpdated = time.time() self.lastAccessed = time.time() self.name = n

def delete(self) -> bool:
    if self.parent is None:
        return False
    return self.parent.delete_entry(self)

def size(self) -> int:
    raise NotImplementedError

# Getters and setters
def get_creation_time(self) -> float:
    return self.created

def get_last_updated_time(self) -> float:
    return self.lastUpdated

def get_last_accessed_time(self) -> float:
    return self.lastAccessed

def change_name(self, n: str):
    self.name = n

def get_name(self) -> str:
    return self.name

A class to represent a File (Inherits from Entry)

class File(Entry): def init(self, n: str, p: 'Entry', sz: int): super().init(n, p) self.size = sz

def size(self) -> int:
    return self.size

def get_contents(self) -> str:
    return self.content

def set_contents(self, c: str):
    self.content = c

A class to represent a Directory (Inherits from Entry)

class Directory(Entry): def init(self, n: str, p: 'Entry' = None): super().init(n, p) self.contents: List[Entry] = []

def size(self) -> int:
    size = 0
    for e in self.contents:
        size += e.size()
    return size

def number_of_files(self) -> int:
    count = 0
    for e in self.contents:
        if isinstance(e, Directory):
            count += 1  # Directory counts as a file
            count += e.number_of_files()
        elif isinstance(e, File):
            count += 1
    return count

def delete_entry(self, entry: Entry) -> bool:
    if entry in self.contents:
        self.contents.remove(entry)
        return True
    return False

def add_entry(self, entry: Entry):
    self.contents.append(entry)

def get_contents(self) -> List[Entry]:
    return self.contents

if name == 'main': root = Directory('root') file1 = File('file1.txt', root, 100) file2 = File('file2.txt', root, 200) root.add_entry(file1) root.add_entry(file2) print('Total size:', root.size()) print('Total files:', root.number_of_files())

JavaScript

class Entry { constructor(n, p = null) { this.parent = p; this.created = Date.now(); this.lastUpdated = Date.now(); this.lastAccessed = Date.now(); this.name = n; }

delete() {
    if (this.parent === null)
        return false;
    return this.parent.deleteEntry(this);
}

size() {
    throw new Error('Method not implemented.');
}

// Getters and setters
getCreationTime() {
    return this.created;
}

getLastUpdatedTime() {
    return this.lastUpdated;
}

getLastAccessedTime() {
    return this.lastAccessed;
}

changeName(n) {
    this.name = n;
}

getName() {
    return this.name;
}

}

class File extends Entry { constructor(n, p, sz) { super(n, p); this.size = sz; }

size() {
    return this.size;
}

getContents() {
    return this.content;
}

setContents(c) {
    this.content = c;
}

}

class Directory extends Entry { constructor(n, p = null) { super(n, p); this.contents = []; }

size() {
    let size = 0;
    for (let e of this.contents)
        size += e.size();
    return size;
}

numberOfFiles() {
    let count = 0;
    for (let e of this.contents) {
        if (e instanceof Directory) {
            count++; // Directory counts as a file
            count += e.numberOfFiles();
        } else if (e instanceof File)
            count++;
    }
    return count;
}

deleteEntry(entry) {
    const index = this.contents.indexOf(entry);
    if (index!== -1) {
        this.contents.splice(index, 1);
        return true;
    }
    return false;
}

addEntry(entry) {
    this.contents.push(entry);
}

getContents() {
    return this.contents;
}

}

const root = new Directory('root'); const file1 = new File('file1.txt', root, 100); const file2 = new File('file2.txt', root, 200);

root.addEntry(file1); root.addEntry(file2);

console.log('Total size:', root.size()); console.log('Total files:', root.numberOfFiles());

`

Alternatively, we could have implemented Directory such that it contains separate lists for files and subdirectories. This makes the nurnberOfFiles () method a bit cleaner, since it doesn't need to use the instanceof operator, but it does prohibit us from cleanly sorting files and directories by dates or names. For data block allocation, we can use bitmask vector and linear search (see “Practical File System Design”) or B+ trees (see Reference or Wikipedia).

**References:

https://stackoverflow.com/questions/14126575/data-structures-used-to-build-file-systems

This article is contributed by

**Mr. Somesh Awasthi

write.geeksforgeeks.org

or mail your article to review-team@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.