【发布时间】:2019-11-27 13:43:46
【问题描述】:
我似乎无法解决我的递归问题。所以我有这个 Version 对象,其中包含对它所依赖的其他版本对象的引用列表。
版本
{
"id": "id1",
"version": "1",
"dependencies": [
{
"id": "id2"
},
{
"id": "id3"
}
]
}
当我检索这个对象时,我还必须检索它的依赖项以及依赖项的依赖项,直到最终结束,这看起来像这样
版本号
{
"id": "id1",
"version": "1",
"dependencies": [
{
"id": "id2",
"version": "2",
"dependencies": [
{
"id": "id4",
"version": "4",
"dependencies": []
}
]
},
{
"id": "id3",
"version": "3",
"dependencies": []
}
]
}
这是我检索版本的递归函数
public VersionDto getVersion(String id)
{
//Retrieves from database
Version version = versionDAO.getVersion(id);
//Convert to Dto (basic fields)
VersionDto versionDto = new VersionDto(version);
//Recursivly retrieve dependencies
for (Map<String, String> dep : version.getDependencies()) {
VersionDto dto = new VersionDto();
//Recursive call
dto = getVersion(dep.get("id"));
versionDto.getDependencies().add(dto);
}
return versionDto;
}
但是,如果版本可能是嵌套依赖项之一的依赖项,例如 v1 -> v2 -> v4 -> v1 导致无限重复,我会遇到可能的无限循环问题。
知道我该如何解决和防止这个无限循环,以便如果版本都准备好更早发生,它应该跳过它?
编辑:使用全局列表的解决方案
public VersionDto getVersion(String id)
{
//Check global list contains version
if (visited.contains(id)) {
return null;
}
visited.add(docId);
//Retrieves from database
Version version = versionDAO.getVersion(id);
//Convert to Dto (basic fields)
VersionDto versionDto = new VersionDto(version);
//Recursivly retrieve dependencies
for (Map<String, String> dep : version.getDependencies()) {
VersionDto dto = new VersionDto();
//Recursive call
dto = getVersion(dep.get("id"));
if(dep!= null) {
versionDto.getDependencies().add(dto);
}
}
return versionDto;
}
【问题讨论】:
-
简而言之:你要么必须标记已经访问过的节点,要么记录你已经访问过的节点。无论哪种情况,您都必须在遇到节点时检查您是否已经访问过它。
-
你想要什么行为,具体来说?您的数据有一个循环,您的代码尽职尽责地遵循该循环。
-
您应该拥有所有访问过的 VersionDto 的结构,并且只有在它们不在列表中时才添加它们。也许如果您添加有关数据结构的更多信息,我可以提供更多信息。
-
在所有递归函数中,你应该有一个结束条件来避免stackoverflow。也许您可以保留一个临时结构来定义已探索的依赖项?
标签: java recursion infinite-recursion