时间:2011-07-07 16:22:25

标签: java algorithm tree

  

可能重复:
  Finding all cycles in graph

我有一个任务,我一直在缠绕我的大脑,仍然有一个麻烦补充它。这就是:有一个班级:

public class Package {
private String name;
public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

private List<Package> dependencies;

public List<Package> getDependencies() {
    return dependencies;
}

public void setDependencies(List<Package> dependencies) {
    this.dependencies = dependencies;
}

public Package(String name){
    this.name = name;
    this.dependencies = new ArrayList<Package>();
}
  //any bunch of methods here))
}

另外还有一个:

public class Project {
private String name;
private List<Package> packages = new ArrayList<Package>();

public boolean hasCyclic(){
    //**//implementation should be here
}

}

我需要查找项目中的包列表是否具有循环依赖性。例如,A-> B-> C-> B-发现,返回真或A-> C-> Z-> A-找到,返回真。 首先想到的是获取所有包的名称,对它们进行排序并查找重复项。但是在某个地方,在我的大脑深处,有些东西告诉我它不是最理想的解决方案。你能帮助我吗?非常感谢你。

5 个答案:

答案 0 :(得分:3)

这基本上是“有向图中的检测周期”问题。

我无法击败已在SO中发布的answer解释如何解决此问题。

答案 1 :(得分:2)

有一个周期&lt; ==&gt; DFS林(从任何起点)都有一个后分支。

线性运行时间。简单的实施。

答案 2 :(得分:1)

将项目的依赖关系视为树,然后只需对树进行深度优先遍历,在访问每个节点时跟踪包名称。如果在遍历到达最高级别之前遇到重复的名称,那么您就具有循环依赖性。

答案 3 :(得分:0)

有许多变体具有不同的内存/执行时间特征。一些想法是

  • 将所有依赖项放在HashMap中,检测周期意味着在执行写入检查时查找非空值
  • 使用两个“指针”来遍历列表,其中一个指针比另一个指针更快。
    • 指针将终止,或者最终会在循环循环中追赶,使得指针A处的元素与指针B中的元素相同。
  • 在插入时提供检查。插入新元素时,遍历列表以查看是否已存在要插入的元素。

答案 4 :(得分:0)

这就是我提出的代码。似乎工作)

package com.mycompany.app;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

public class Package {
private String name;
private List<Package> dependencies;
private List<String> allNames = new ArrayList<String>();
public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public List<Package> getDependencies() {
    return dependencies;
}

public void setDependencies(List<Package> dependencies) {
    this.dependencies = dependencies;
}

public Package(String name){
    this.name = name;
    this.dependencies = new ArrayList<Package>();
}

public boolean hasPackages(){
    return !dependencies.isEmpty();
}

public List<String> getAllNames(){
    allNames = new ArrayList<String>();
    allNames.add(name);
    for (Package pkg : dependencies){
        if (pkg.hasPackages()){
            allNames.addAll(pkg.getAllNames());
        }
        else{
            allNames.add(pkg.getName());
        }
    }

    return allNames;
}

public Package addPackage(Package pkg){
    dependencies.add(pkg);
    return this;

}

public boolean hasCyclic(){
    List<String> names = getAllNames();
    Set<String> visited = new HashSet<String>();
    for (String name : names){
        if (visited.contains(name)){
            return true;
        }
        else{
            visited.add(name);
        }
    }
    return false;
}
}