我在一个类似树的结构中工作,其中每个父节点可以包含多个子节点,每个子节点只能有一个父节点,就像文件系统中的目录结构一样。
我已经完成了很多这些并且有许多不同的方法来解决鸡与蛋的问题,而不是我现在要与你分享,但我想知道是否有一个不那么优化的一般到目前为止我一直无视的设计模式来解决它。
现在,问题在于当您将父节点设置为子节点时,父节点必须将此新节点添加到其内部后代列表中,并且当您向父节点添加子节点时,儿子必须更新它。父母,所有这一切都是为了保持一个连贯的树,否则你最终会有父母,他们的儿子不会认出他们是父亲,反之亦然...
让我们看一个例子(我将使用JAVA),因为代码中的代码问题比段落中的解释更好:
class Node {
private Node parent;
private ArrayList<Node> sons=new ArrayList<Node>();
public void setParent(Node parent) {
this.parent = parent;
parent.addSon(this);
}
public void addSon(Node son) {
this.sons.add(son);
son.setParent(this);
}
}
好的,为了简单起见,这是最简单的形式,尽管还有其他事情需要处理(例如,从其前一个父节点移除子节点)。我很确定你已经看到了我们这里的递归问题。
或多或少明显的方法是在运行时检查儿子是否已将此作为其父级分配,因此我将这些方法重写为:
public void addSon(Node son) {
this.sons.add(son);
if (son.parent != this)
son.setParent(this);
}
但我想知道是否有更好的方法来解决这个问题。例如,另一种节省一些冗余调用的方法可能是使用静态方法,例如:
class Node {
private Node parent;
private ArrayList<Node> sons=new ArrayList<Node>();
public static assignSon(Node parent, Node son) {
parent.sons.add(son);
son.parent = parent;
}
}
所以,如果assignSon是唯一可以用来将儿子与父亲联系起来的方法,这解决了鸡蛋和蛋的问题,但从外面使用它也不太直观,你必须要写下更多代码,你知道,之前你可以做些什么:
son.setParent(parent);
或者
parent.addSon(son);
你现在要写:
Node.assignSon(parent, son);
这不是什么大不了的事,但仍然......好吧,无论如何。如果你知道这个问题的最佳方法,并且你想与这个社区分享,那么我将非常感谢!
TIA!
答案 0 :(得分:1)
我认为为了避免鸡和蛋的问题,你可以编写一个调用setParent的addSon方法,反之亦然,但不是两种方式,如下所示。当我必须实现一种上升树的方法时,我一直在树中使用它。
class Node {
private Node parent;
private ArrayList<Node> sons=new ArrayList<Node>();
private void setParent(Node parent) {
this.parent = parent;
}
public void addSon(Node son) {
this.sons.add(son);
son.setParent(this);
}
}
答案 1 :(得分:1)
我会使用与 @uoyilmaz 相同的代码,但请记住更新旧的父母(如果已经存在),否则如果您要分配一个已分配给其他人的儿子,您将得到一些不一致性。
例如,如果来自这棵树:
a
/ | \
b c d
您将d
作为b
a
/ \
b c
|
d
a
仍然会引用d
节点。
所以也许这样的事情应该有效:
class Node {
private Node parent;
private ArrayList<Node> sons=new ArrayList<Node>();
private void setParent(Node parent) {
this.parent = parent;
}
public void addSon(Node son) {
if(!this.sons.contains(son)) {
this.sons.add(son);
if(son.parent != null) {
son.parent.sons.remove(son);
}
son.setParent(this);
}
}
}