代表软件包安装和系统依赖关系的最佳数据结构

Best Data Structure representing Package Installation and System Dependencies

本文关键字:关系 最佳 数据结构 依赖 系统 软件包 安装      更新时间:2023-10-16

我正在尝试创建一个基于面试过程的程序(我选择Java,但可以是C/C++或GoLang(,以表示/模拟软件包安装和系统依赖关系,就像Linux/Unix环境中存在的那样。 基本上,我将满足以下要求:

1( 维护已安装软件包及其依赖项的记录。
2( 支持显式安装软件包以响应命令(除非已安装(。
3( 如果需要安装另一个软件包,则支持隐式安装一个软件包。
4( 支持显式删除包以响应命令(如果不需要支持其他包(。
5( 如果不再需要某个包来支持另一个组件,则支持隐式删除该包。

在安装包之前,自动安装它需要的所有包。 在删除包之前,请确认没有其他包需要它。必须先手动删除依赖包,然后才能删除包。

我想要最好的数据结构(以及我可以检查的链接(的提示,我可以用来做到这一点。我尝试使用队列列表作为存储依赖项的一种方式和一个队列来存储已安装的软件包,但我不确定这是否是最好的方法,例如:

...
ArrayList<Queue<String>> dependencies = new ArrayList<>(capacity);
Queue<String> pkgInstalled = new LinkedList<String>();
...

该过程将从用户捕获条目数据,直到 END 命令。 命令语法为:

依赖项目1 项目2 项目(n(:包裹项目1取决于包裹项目2(和项目3或任何;

安装item1:安装 item 1 和 item 1 所需的任何其他软件包。

删除项目 1:删除项目 1,如果可能,删除项目 1 所需的包。

列表:列出所有当前安装的软件包的名称。

END:标记输入的结束(当单独用于一行中时(。

1( 按照每个回显的"安装"或"删除"行执行响应时执行的操作,确保操作按正确的顺序给出。
2( 对于 LIST 命令,显示当前安装的组件的名称。
3( 对于 DEPEND 和 END 命令,除了回显之外,不会产生任何输出。
4( 对于 DEPEND 命令,每个项目只有一个依赖项列表。

我不知道Queue在这个练习(或LinkedList(中的价值,因为您将希望能够随机访问包的依赖项。

我会建议

Map<String, Set<String>> dependsOn = new HashMap<>();
Map<String, Set<String>> requiredBy = new HashMap<>();

这样,当你删除一个包时,你可以找到它拉入的所有包(dependsOn.get(packageToDelete)(,并从requiredBy中的每个条目中删除packageToDelete;如果这让requiredBy集为空,那么也可以删除该包。

我还建议在添加新的根包时,使用Set来添加依赖包。 处理它们的顺序并不重要,快速和避免重复更有用。

最初,我认为使用唯一的完全限定包名称作为键会更简单 - 更容易编码和调试。 这需要一种方法来根据包的名称查找包,但这应该已经存在。 但是,如果您愿意,可以为Package类实现equals()hashcode(),并直接将它们用作Map键。

为了阐明这可能是如何工作的,下面是一个示例:

public Set<String> addDependencies(Item pkg, Item... dependencies) {
Set<String> pkgDependsOn = dependsOn.get(pkg.getFullyQualifiedName());
if (pkgDependsOn == null) {
pkgDependsOn = new HashSet<>();
dependsOn.put(pkg.getFullyQualifiedName(), pkgDependsOn);
}
pkgDependsOn.addAll(Stream.of(dependencies).map(dep -> dep.getFullyQualifiedName()).collect(Collectors.toSet()));
return pkgDependsOn;
}

(我可能改用Map.merge(),但在写出来后,我认为它足够复杂,令人困惑。

返回生成的依赖项Set可能是矫枉过正的,但我可以想象在某些情况下它可能很有用。

如果您选择使用包本身作为密钥,则如下所示:

public Set<Item> addDependencies(Item pkg, Item... dependencies) {
Set<Item> pkgDependsOn = dependsOn.get(pkg);
if (pkgDependsOn == null) {
pkgDependsOn = new HashSet<>();
dependsOn.put(pkg, pkgDependsOn);
}
pkgDependsOn.addAll(Arrays.asList(dependencies));
return pkgDependsOn;
}

我也没有进行错误检查(例如,如果您使包依赖于自身(,空检查等。