如何在对象层次结构中找到循环?

时间:2015-08-10 07:30:56

标签: java algorithm cyclomatic-complexity object-graph

有一个班级Company,它引用了Company的另一个实例来代表parent。可以说有四家公司c1c2c3& c4c2c3c4已将母公司设为c1

例如:

public class Company {
  public Company parent;

  public Company() { }
  public Company(Company parent) {
    this.parent = parent;
  }

  public static void main(String[] args) {
    Company c1 = new Company();
    Company c2 = new Company(c1);
    Company c3 = new Company(c1);
    Company c4 = new Company(c1);
}

如果我们将c2设置为c1的母公司:

c1.parent = c2;

然后它将在公司层次结构中创建一个Cyclomatic Complexity无限循环,我们必须在系统中避免这种循环。

我们希望能够在运行时检测到 。在上述情况下,检查同一类对象的圈复杂度的最佳算法是什么?

3 个答案:

答案 0 :(得分:6)

您的任务与圈复杂度无关。您的实体基本上形成一个图形,并且您想要检测其中的循环。常见的方法是执行DFS

您可以找到大量示例over the internet

答案 1 :(得分:1)

我已经以编程方式解决了这个问题,创建了一个本地Set个已处理对象,并让它在每次调用递归方法时作为输入参数传播。

例如:

public void myMethod(Company c)
{
    Set<Company> visitedCompanies=new HashSet<Company>();
    visitedCompanies.add(c);
    myPrivateMethod(c, visitedCompanies);
}

private void myPrivateMethod(Company c, Set<Company> visitedCompanies)
{
    if (visitedCompanies.contains(c))
    {
        // Cylce detected
    }
    else
    {
        //... do some stuff

        // Go upwards in the hierarchy
        if (c.getParent()!=null)
        {
            visitedCompanies.add(c);
            myPrivateMethod(c.getParent(), visitedCompanies);
        }
    }

对于科西嘉,您必须先确保您的班级公司是可转化的:它会正确覆盖hashCodeequals

请注意,此算法甚至可以在公司抽象之外实现(如本例所示),因为它在每个调用中传播Company对象作为遍历状态的一部分(以及集合)。这不是强制性的,因为这些方法本身可能是公司抽象的一部分,但 必须将该集合作为输入参数传播。

答案 2 :(得分:0)

您可以将private async void Button_Click(object sender, RoutedEventArgs e) { await LoadingDialogAsync(); SaveAndLoadData.SaveUserData(ApplicationData.UserData); MainWindowLogic.LogIntoWebsites(); } private async Task LoadingDialogAsync() { var controller = await this.ShowProgressAsync("Logging In...", ""); } 设置为parent,并使用方法private更改parent的值。然后:

setParent(Company)

通常不好的做法是使用public boolean setParent(Company parent) { Company curr = parent; while (curr != null) { if (curr.equals(this)) { return false; // Failed as cycle } else { curr = curr.getParent(); } } this.parent = parent; return true; } 变量,因为它会破坏封装。

如果您无法将字段更改为public,则:

private

修改:更改public List<Company> hasCycle(List<Company> companies) { while (companies.size() > 0) { List<Company> cycle = new ArrayList<Company>(); Company curr = companies.get(companies.length() - 1); cycle.add(curr); while (curr.parent != null) { curr = curr.parent; if (cycle.contains(curr)) { return cycle; // Cycle detected } cycle.add(curr); } companies.removeAll(cycle); // Remove all elements we traversed through just now } return null; } 的返回值,以返回包含所有公司的hasCycle进行进一步处理(打印出来,删除等)。