Java 遍历图的顶点作为该顶点的一种方法

Java 遍历图的顶点作为该顶点的一种方法,java,algorithm,Java,Algorithm,我有一个目前无法解决的问题 假设我有一个类成员,包含与给定成员相关的成员列表的信息: ArrayList链接 另外,这个类还有一个方法叫做canBeLinked(Member) 它显然返回布尔值,定义特定成员是否可以直接或间接地与给定成员链接 我所说的“直接”是指普通关系A->B;如果例如A->B和B->C,那么它也应该返回true。 还要记住,如果A->B,那么B->A。 我们得到了一个无向图的模型 我的困惑是如何实现这个功能;我猜它一定是递归的,但重点是它不是两个参数的函数(例如,如果它是静

我有一个目前无法解决的问题

假设我有一个类
成员
,包含与给定成员相关的成员列表的信息:
ArrayList链接

另外,这个类还有一个方法叫做
canBeLinked(Member)

它显然返回布尔值,定义特定成员是否可以直接或间接地与给定成员链接

我所说的“直接”是指普通关系A->B;如果例如A->B和B->C,那么它也应该返回true。 还要记住,如果A->B,那么B->A。 我们得到了一个无向图的模型

我的困惑是如何实现这个功能;我猜它一定是递归的,但重点是它不是两个参数的函数(例如,如果它是静态函数,我们可以很容易地编写函数
canBeLinked(成员a,成员b)
,互联网上有很多这样的图的实现)

我的第一个方法是这样写:

public boolean canBeLinked(Member member) {
   if (this.links.contains(member)) {
       return true;
   }
   else {
       for (Member m : links)
           if (m.canBeLinked(member)) return true;
   }
   return false;
}
我肯定会得到一个StackOverflowException; 假设我们有这样的关系:

A -> B
B -> D
B -> E
D -> C
E -> C
打电话的时候

a.canBeLinked(c) 
我们得到: 1) 首先,我们检查“c”是否已经在“a”的成员名单中; 2) 这不是真的,所以进入for循环; 3) 由于我们在名单中只有一名成员(它是“b”),我们称之为b.canBeLinked(c); 4) “c”也不是“b”列表中的成员,因此它也会进入“for”语句 5) 现在我们遇到了麻烦,因为“b”的列表不仅包含“e”和“d”,而且还包含“a”,这将导致我们进入第1页;它将永远持续(直到内存耗尽)


你能解释一下如何解决这个问题吗?我很确定这是一个很简单的问题,但我只是被这个问题困住了,而且肯定错过了它的一些关键点。

幸运的是,修复相当简单;您需要跟踪哪些
成员
在搜索中已被访问,例如使用
集合
,并且不要循环返回访问任何已被访问的
成员。在查询链接的
成员
之前,将当前的
成员
添加到已访问的组中

由于递归函数现在需要传递访问的成员集,因此最好将其拆分为从公共方法调用的
private
protected
方法

public boolean canBeLinked(Member member) 
{
  return canBeLinked(member, new HashSet<>());
}

private boolean canBeLinked(Member member, Set<Member> visited)
{
  if (this.links.contains(member)) {
      return true;
  }
  else {
    visited.add(this);
    for (Member m : links)
    {
      if (!visited.contains(m)) return m.canBeLinked(member, visited);
    }
  }
  return false;
}
public boolean canBeLinked(成员)
{
返回canBeLinked(成员,newhashset());
}
私有布尔canBeLinked(成员,访问集)
{
if(this.links.contains(成员)){
返回true;
}
否则{
已访问。添加(此);
for(成员m:链接)
{
如果(!visted.contains(m))返回m.canBeLinked(成员,已访问);
}
}
返回false;
}