虚拟文件系统
华为OD机试双机位C卷 - 华为OD上机考试双机位C卷 100分题型
华为OD机试双机位C卷真题目录点击查看: 华为OD机试双机位C卷真题题库目录|机考题库 + 算法考点详解
题目描述
构建一个虚拟文件系统,此文件系统须提供如下两种功能:
- 添加文件(addfile命令)
- 展示文件夹内容(ls)
其中通过addfile命令可以添加文件到指定目录,例如addfile /src/main/java/x.java。通过ls命令可以输出本目录下所有文件夹和文件命令,例如ls /src输出x.java,ls /src/main/java输出x.java,其中星号用于标识文件夹,而非末端文件。
输入描述
每行输入一个添加文件的指令,包括addfile 固定前缀和/开头的文件路径。
最后一行输入一个展示目录内容指令,包括ls 固定前缀和/开头的文件夹路径名
输出描述
用两个空格分割文件夹/文件,输出本目录下所有文件夹/文件即可,按照文件夹/文件的字符串字典序排序输出。
用例1
输入
none
addfile /src/main/java/democlass.java
addfile /src/main/java/demoentity.java
addfile /src/main/java/com/demo/it/demoservice.class
addfile /src/main/resource/application.yml
addfile /src/main/resource/log.yml
ls /src
输出
none
main*
用例2
输入
none
addfile /src/main/java/democlass.java
addfile /src/main/java/demoentity.java
addfile /src/main/java/com/demo/it/demoservice.class
addfile /src/main/resource/application.yml
addfile /src/main/resource/log.yml
ls /src/main/java
输出
none
com* democlass.java demoentity.java
题解
思路:模拟
- 利用输入的添加文件命令,构建出对应的文件树结构(借助类/结构体)来实现。
- 对于添加文件命令的解析,分割出具体路径然后进行解析,如果对应目录或文件不存在则创建。此时可以注意一个特殊情况
/a/b和/a/b/c.txt这两个文件目录,需要将目录和文件进行区分,这里结合题目要输出的目录可以人为在文件夹名后添加一个*以达到区分。 ls 文件夹解析逻辑和创建文件差不多,找到对应目录后将该目录下的文件/文件夹添加到结果数组。排序之后进行输出即可。
C++
c++
#include<iostream>
#include<vector>
#include<string>
#include <utility>
#include <sstream>
#include<algorithm>
#include<cmath>
#include<map>
using namespace std;
struct Node {
map<string, Node*> children;
bool isFile;
Node() {
isFile = false;
}
};
// 根目录
Node* root = new Node();
// 通用 切割函数 函数 将字符串str根据delimiter进行切割
vector<string> split(const string& str, const string& delimiter) {
vector<string> result;
size_t start = 0;
size_t end = str.find(delimiter);
while (end != string::npos) {
result.push_back(str.substr(start, end - start));
start = end + delimiter.length();
end = str.find(delimiter, start);
}
// 添加最后一个部分
result.push_back(str.substr(start));
return result;
}
// 添加文件
void addFile(const string& cmd) {
// 切割获取文件目录
string filePath = split(cmd, " ")[1];
vector<string> parts = split(filePath, "/");
Node* cur = root;
for (int i = 0; i < parts.size(); i++) {
string name = parts[i];
if (name.empty()) {
continue;
}
bool isFile = false;
// 最后一个是文件
if (i == parts.size() - 1) {
isFile = true;
}
if (!isFile) {
name += "*";
}
if (!cur->children.count(name)) {
cur->children[name] = new Node();
}
cur = cur->children[name];
cur->isFile = isFile;
}
}
// ls 命令
void ls(const string& cmd, vector<string>& res) {
string path = split(cmd, " ")[1];
Node* cur = root;
vector<string> parts = split(path, "/");
// 找到目录
for (int i = 0; i < parts.size(); i++) {
string name = parts[i];
if (name.empty()) {
continue;
}
name += "*";
if (!cur->children.count(name)) return;
cur = cur->children[name];
}
bool first = true;
for (auto& [name, node] : cur->children) {
res.push_back(name);
}
}
int main() {
vector<string> inputs;
string line;
// 读取所有输入
while (getline(cin, line)) {
inputs.push_back(line);
}
// 最后一行是 ls
int n = inputs.size();
for (int i = 0; i < n - 1; i++) {
string cmd = inputs[i];
addFile(cmd);
}
string lsCmd = inputs[n - 1];
vector<string> res;
ls(lsCmd, res);
sort(res.begin(), res.end());
int m = res.size();
//输出结果
for (int i = 0; i < m; i++) {
cout << res[i];
if (i != m -1) {
cout << " ";
}
}
return 0;
}
JAVA
JAVA
import java.util.*;
public class Main {
static class Node {
Map<String, Node> children = new HashMap<>();
boolean isFile = false;
}
static Node root = new Node();
// 添加文件
static void addFile(String cmd) {
String filePath = cmd.split(" ")[1];
String[] parts = filePath.split("/");
Node cur = root;
for (int i = 0; i < parts.length; i++) {
String name = parts[i];
if (name.isEmpty()) continue;
boolean isFile = i == parts.length - 1;
if (!isFile) name += "*";
cur.children.putIfAbsent(name, new Node());
cur = cur.children.get(name);
cur.isFile = isFile;
}
}
// ls 命令
static void ls(String cmd, List<String> res) {
String path = cmd.split(" ")[1];
String[] parts = path.split("/");
Node cur = root;
for (String name : parts) {
if (name.isEmpty()) continue;
name += "*";
if (!cur.children.containsKey(name)) return;
cur = cur.children.get(name);
}
for (String name : cur.children.keySet()) {
res.add(name);
}
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
List<String> inputs = new ArrayList<>();
while (sc.hasNextLine()) {
inputs.add(sc.nextLine());
}
int n = inputs.size();
for (int i = 0; i < n - 1; i++) addFile(inputs.get(i));
String lsCmd = inputs.get(n - 1);
List<String> res = new ArrayList<>();
ls(lsCmd, res);
Collections.sort(res);
for (int i = 0; i < res.size(); i++) {
System.out.print(res.get(i));
if (i != res.size() - 1) System.out.print(" ");
}
}
}
Python
python
import sys
class Node:
def __init__(self):
self.children = {}
self.isFile = False
root = Node()
def addFile(cmd):
filePath = cmd.split(" ")[1]
parts = filePath.split("/")
cur = root
for i, name in enumerate(parts):
if not name:
continue
isFile = i == len(parts) - 1
if not isFile:
name += "*"
if name not in cur.children:
cur.children[name] = Node()
cur = cur.children[name]
cur.isFile = isFile
def ls(cmd):
path = cmd.split(" ")[1]
parts = path.split("/")
cur = root
for name in parts:
if not name:
continue
name += "*"
if name not in cur.children:
return []
cur = cur.children[name]
return list(cur.children.keys())
# 读取输入
inputs = [line.strip() for line in sys.stdin if line.strip()]
for cmd in inputs[:-1]:
addFile(cmd)
res = ls(inputs[-1])
res.sort()
print(" ".join(res))
JavaScript
js
const readline = require('readline');
class Node {
constructor() {
this.children = {};
this.isFile = false;
}
}
let root = new Node();
// 创建文件命令
function addFile(cmd) {
let filePath = cmd.split(" ")[1];
let parts = filePath.split("/");
let cur = root;
for (let i = 0; i < parts.length; i++) {
let name = parts[i];
if (!name) continue;
let isFile = i === parts.length - 1;
if (!isFile) name += "*";
if (!(name in cur.children)) cur.children[name] = new Node();
cur = cur.children[name];
cur.isFile = isFile;
}
}
// ls命令
function ls(cmd) {
let path = cmd.split(" ")[1];
let parts = path.split("/");
let cur = root;
for (let name of parts) {
if (!name) continue;
name += "*";
if (!(name in cur.children)) return [];
cur = cur.children[name];
}
return Object.keys(cur.children);
}
const rl = readline.createInterface({
input: process.stdin
});
let inputs = [];
rl.on('line', (line) => {
inputs.push(line.trim());
}).on('close', () => {
for (let i = 0; i < inputs.length - 1; i++) addFile(inputs[i]);
let res = ls(inputs[inputs.length - 1]);
res.sort();
console.log(res.join(" "));
});
Go
go
package main
import (
"bufio"
"fmt"
"os"
"sort"
"strings"
)
type Node struct {
children map[string]*Node
isFile bool
}
var root = &Node{children: make(map[string]*Node)}
// 创建文件
func addFile(cmd string) {
parts := strings.Split(cmd, " ")[1]
path := strings.Split(parts, "/")
cur := root
for i, name := range path {
if name == "" {
continue
}
isFile := i == len(path)-1
if !isFile {
name += "*"
}
if _, ok := cur.children[name]; !ok {
cur.children[name] = &Node{children: make(map[string]*Node)}
}
cur = cur.children[name]
cur.isFile = isFile
}
}
// ls命令
func ls(cmd string) []string {
parts := strings.Split(cmd, " ")[1]
path := strings.Split(parts, "/")
cur := root
for _, name := range path {
if name == "" {
continue
}
name += "*"
next, ok := cur.children[name]
if !ok {
return []string{}
}
cur = next
}
res := []string{}
for k := range cur.children {
res = append(res, k)
}
return res
}
func main() {
scanner := bufio.NewScanner(os.Stdin)
inputs := []string{}
for scanner.Scan() {
line := scanner.Text()
if strings.TrimSpace(line) != "" {
inputs = append(inputs, line)
}
}
for i := 0; i < len(inputs)-1; i++ {
addFile(inputs[i])
}
res := ls(inputs[len(inputs)-1])
// 升序排序
sort.Strings(res)
fmt.Print(strings.Join(res, " "))
}
C语言
cpp
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct Node {
char *name; // 文件/文件夹名字
int isFile; // 是否是文件
struct Node **children; // 子节点数组
int childCount; // 子节点数量
int childCap; // 子节点容量
} Node;
// 根目录
Node *root;
// 创建节点
Node* createNode(const char *name, int isFile) {
Node *node = (Node*)malloc(sizeof(Node));
node->name = malloc(strlen(name) + 1);
strcpy(node->name, name);
node->isFile = isFile;
node->childCount = 0;
node->childCap = 4;
node->children = malloc(sizeof(Node*) * node->childCap);
return node;
}
// 查找子节点
Node* findChild(Node *parent, const char *name) {
for (int i = 0; i < parent->childCount; i++) {
if (strcmp(parent->children[i]->name, name) == 0)
return parent->children[i];
}
return NULL;
}
// 添加文件
void addFile(char *cmd) {
char *filePath = cmd + 8; // 跳过 "addfile "
Node *cur = root;
char path[512];
strcpy(path, filePath);
char *token = strtok(path, "/");
while (token) {
char name[512];
int isFile = 0;
token[strcspn(token, "\n")] = 0;
char *next = strtok(NULL, "/");
if (!next) isFile = 1; // 最后一个是文件
if (!isFile) sprintf(name, "%s*", token);
else strcpy(name, token);
Node *child = findChild(cur, name);
if (!child) {
child = createNode(name, isFile);
if (cur->childCount == cur->childCap) {
cur->childCap *= 2;
cur->children = realloc(cur->children, sizeof(Node*) * cur->childCap);
}
cur->children[cur->childCount++] = child;
}
cur = child;
token = next;
}
}
// qsort 比较函数
int cmp(const void *a, const void *b) {
Node *na = *(Node**)a;
Node *nb = *(Node**)b;
return strcmp(na->name, nb->name);
}
// ls 命令
void ls(char *cmd) {
char *path = cmd + 3; // 跳过 "ls "
Node *cur = root;
char p[512];
strcpy(p, path);
char *token = strtok(p, "/");
while (token) {
token[strcspn(token, "\n")] = 0;
if (strlen(token) == 0) {
token = strtok(NULL, "/");
continue;
}
char name[512];
sprintf(name, "%s*", token);
Node *child = findChild(cur, name);
if (!child) return; // 目录不存在
cur = child;
token = strtok(NULL, "/");
}
// 排序输出
qsort(cur->children, cur->childCount, sizeof(Node*), cmp);
for (int i = 0; i < cur->childCount; i++) {
printf("%s", cur->children[i]->name);
if (i != cur->childCount - 1) printf(" ");
}
}
int main() {
root = createNode("/", 0);
char line[512];
char *inputs[1000];
int inputCount = 0;
// 读取所有输入
while (fgets(line, sizeof(line), stdin)) {
line[strcspn(line, "\n")] = 0;
inputs[inputCount] = malloc(strlen(line) + 1);
strcpy(inputs[inputCount++], line);
}
// 最后一行是 ls
for (int i = 0; i < inputCount - 1; i++) {
addFile(inputs[i]);
}
ls(inputs[inputCount - 1]);
return 0;
}