2015-09-10 3 views
0

У меня есть дерево:реализация Дерево бросает StackOverflowError

public class Node<T> { 
    private T data; 
    private Node<T> parent; 
    private Map<T, Node<T>> children; 

    public Node(T data, Node<T> parent) { 
     this.data = data; 
     this.parent = parent; 
    } 

    public Node(T data) { 
     this.data = data; 
    } 

    public boolean hasChildren() { 
     if (this.children != null) { 
      return this.children.size() > 0; 
     } 
     return false; 
    } 

    public void setParent(Node<T> parent) { 
     parent.addChild(this); 
     this.parent = parent; 
    } 

    public void addChild(T data) { 
     Node<T> child = new Node<T>(data); 
     child.setParent(this); 
     this.children.put(child.data, child); 
    } 

    public void addChild(Node<T> child) { 
     child.setParent(this); 
     this.children.put(child.data, child); 
    } 
} 

Затем я пытаюсь заполнить это следующим образом:

Node<String> parentNode = new Node<String>("Parent"); 
Node<String> childNode = new Node<String>("Child"); 
childNode.setParent(parentNode); 

Это бросает StackOverflowError, потому что мы застряли в SetParent петли - addChild.

Я попробовал другой путь:

Node<String> parentNode = new Node<String>("Parent"); 
Node<String> childNode = new Node<String>("Child", parentNode); 

Однако childNode.parent.children имеет нулевое значение, и я хотел бы, чтобы иметь childNode в нем.

Как я могу это достичь?

+0

Где в 'Node (T, Node )' конструктора вы думаете, вы добавляете новый ребенок к карте родителя детей? (В общем, непонятно, что вы пытаетесь задать в этом вопросе ... почему новый код не работает или о переполнении стека?) –

+0

@Jon Skeet: отредактирован, лучше? – l0r3nz4cc10

+0

Не совсем так, потому что все еще неясно, пытаетесь ли вы исправить этот второй конструктор или устраните тот факт, что 'childNode.setParent (parentNode)' терпит неудачу. –

ответ

1

Я думаю, вы должны принять рекурсии из картины и обрабатывать последовательность parent-child в прикладном уровне (т.е. используйте childNode.setParent(parentNode); и parentNode.addChild(parentNode); вместе). Вы можете использовать код ниже, он будет работать в обоих направлениях.

public class Node<T> { 
private T data; 
private Node<T> parent; 
private Map<T, Node<T>> children; 

public Node(T data, Node<T> parent) { 
    this.data = data; 
    this.parent = parent; 
    parent.addChild(this); 
} 

public Node(T data) { 
    this.data = data; 
} 

public boolean hasChildren() { 
    if (this.children != null) { 
     return this.children.size() > 0; 
    } 
    return false; 
} 

public void setParent(Node<T> parent) { 
    this.parent = parent; 
} 

public void addChild(T data) { 
    Node<T> child = new Node<T>(data); 
    this.children.put(child.data, child); 
} 

public void addChild(Node<T> child) { 
    this.children.put(child.data, child); 
} 

}

-1

У вас есть исключение StackOverflow, потому что ваш метод «AddChild» называют свой метод «SetParent» и ваш «SetParent» вызов метода «AddChild»

+0

OP уже понял это и упомянул в вопросе. –

0

setParent и addChild призывают друг друга. Для того, чтобы оба вызова addChild или setParent были действительными, необходимо было бы создать частный метод setParentInternal, вызываемый addChild, а не общественностью setParent.

Обратите внимание, что я также реорганизовал addChild, чтобы уменьшить reduncuncy и инициализировать список детей.

public class Node<T> { 
    private T data; 
    private Node<T> parent; 
    private Map<T, Node<T>> children= new HashMap<T, Node<T>>(); 

    public Node(T data, Node<T> parent) { 
     this.data = data; 
     this.parent = parent; 
    } 

    public Node(T data) { 
     this.data = data; 
    } 

    public boolean hasChildren() { 
     if (this.children != null) { 
      return this.children.size() > 0; 
     } 
     return false; 
    } 

    private void setParentInternal(Node<T> parent) { 
     this.parent = parent; 
    } 

    public void setParent(Node<T> parent) { 
     parent.addChild(this); 
     setParentInternal(parent); 
    } 

    public void addChild(T data) { 
     addChild(new Node<T>(data)); 
    } 

    public void addChild(Node<T> child) { 
     child.setParentInternal(this); 
     this.children.put(child.data, child); 
    } 
} 
Смежные вопросы