Алгоритм глубины и степени N-арного дерева

У меня возникли проблемы с парой алгоритмов, которые должны возвращать максимальную степень (максимальное количество дочерних элементов узла) и глубину (размер самой длинной ветви) дерева. Похоже, что с некоторыми древовидными структурами они работают, с некоторыми — нет. Может кто-нибудь, пожалуйста, скажите мне, если я делаю что-то не так с кодом?

Моя древовидная структура

public class Tree<T> {

  public Node<T> root;

  public Tree() {
    root = null;
  }

Моя структура узла:

public class Node<T>{
  public T elem; 
  private Node<T> father;
  private Node<T> child; 
  private Node<T> sibling;
  private T epsilon;

public Node(T elem){   
  this.elem = elem;
  this.father = null;
  this.child = null;
  this.sibling = null;  
}

Алгоритм степени:

public int degree(){
int breadth = 0;
int max = 0;
return auxDegree(this.root, breadth, max);
}

public int auxDegree(Node<T> node, int count, int maxChild){
if(node!=null){
  if(node.getChild()!=null){ 
    maxChild = Math.max(auxDegree(node.getChild(), 0, maxChild), auxDegree(node.getSibling(), 0, maxChild));
    count = countSibling(node.getChild()) + 1;
    return (count>maxChild) ? count : maxChild;
  }else return maxChild;
 }else return maxChild;
}

Наконец, алгоритм глубины:

public int depth(){
  int deepness = 0;
  return auxDepth(this.root, deepness);
}

public int auxDepth(Node<T> node, int maxDepth){
  if(node!=null){
    if(node.getChild()!=null){
       maxDepth = Math.max(maxDepth, auxDepth(node.getChild(), maxDepth));
       maxDepth = maxDepth + 1;
       return maxDepth;
    }else{
      return maxDepth;
    }
  }else return maxDepth;
}

Код вставки:

public Node<T> search(T key){
  return searchAux(this.root, key);
}

private Node<T> searchAux(Node<T> node, T key){
  if(node == null) 
    return null;
  else{
    while(node.getChild() != null && key != node.getElem()){
      node = node.getChild();
      searchAux(node.getSibling(), key); 
    }
  }  
   return node;  
}

public void insert(T father_key, T child_key){
  if(IsEmpty())
    this.root = new Node<T>(child_key);
  else{
    Node<T> node = new Node<T>(child_key);
    Node<T> father = search(father_key);
    if(father.getChild() == null){
      father.setChild(node);
      node.setParent(father);
     }else{
     if (father.getChild() != null){
       Node<T> brother = father.getChild(); 
       while(brother.getSibling() != null){
         brother = brother.getSibling(); 
       }
       brother.setSibling(node);
       node.setParent(father);
      }
    }
  }
}

Структура, которая не работает:

public void Test_Depth(){
  tree.insert(null, e2);
  tree.insert(e2, e3);
  tree.insert(e2, e1);
  tree.insert(e3, e4);
  tree.insert(e4, e5);
  tree.insert(e5, e6);
  tree.insert(e6, e7);
  assertEquals(6,tree.depth());
}

Это возвращает 5, но должно возвращать 6

public void Test_Depth(){
  tree.insert(null, e1);
  tree.insert(e1, e2);
  tree.insert(e1, e3);
  tree.insert(e3, e4);
  tree.insert(e3, e5);
  tree.insert(e3, e6);
  assertEquals(3,tree.degree());
}

Это должно вернуть 3, но возвращает 2

от e1 до e7 — целые числа.


person Leo    schedule 11.05.2017    source источник
comment
Я думаю, что предоставление плохих и хороших древовидных структур поможет проанализировать проблему.   -  person Picard    schedule 11.05.2017
comment
Я добавил их. Извините, что не сделал этого. Дело в том, что они работают почти со всем, что я пробовал, кроме этих двух и еще парочки.   -  person Leo    schedule 11.05.2017
comment
Можете ли вы показать нам свою реализацию вставки (...)?   -  person Brandon McKenzie    schedule 11.05.2017
comment
Сделанный. Метод Insert использует вспомогательный метод Search. Если вам нужны какие-либо разъяснения, пожалуйста, скажите мне   -  person Leo    schedule 11.05.2017
comment
Какой тип e1..e7?   -  person fps    schedule 11.05.2017
comment
Это целые числа   -  person Leo    schedule 12.05.2017


Ответы (1)


Две вещи.

Прежде всего, ваша функция searchAux неверна. Следующая строка бесполезна, поскольку ее возвращаемое значение игнорируется:

searchAux(node.getSibling(), key);

Более того, цикл while позволяет назначать дочерние узлы неправильным родителям. Условие

node.getChild() != null && key != node.getElem()

имеет значение false, если посещаемый вами узел не имеет дочерних элементов, независимо от значения его ключа; это означает, что последующая инструкция return node; может быть выполнена, даже если возвращаемый узел не является искомым родительским узлом.

Это то, что происходит, например, во втором примере. Это ситуация после первых трех insert (вертикальная линия = родитель-потомок, горизонтальная линия = брат и сестра):

e1
|
e2--e3

Все идет нормально. Однако, когда вы вызываете tree.insert(e3, e4), e3 посещается, но игнорируется; Вместо него возвращается e2 (попробуйте пройтись по вашему коду). Таким образом:

e1
|
e2--e3
|
e4

Кстати, вот как в итоге выглядит второе дерево:

e1
|
e2--e3
|
e4
|
e5
|
e6

Второе: первое дерево, насколько я могу судить, правильное, хотя ваш алгоритм поиска неверен. Его глубина равна 5, а не 6 (глубина корневого узла равна нулю):

0: e2
   |
1: e3--e1
   |
2: e4
   |
3: e5
   |
4: e6
   |
5: e7

При этом вот краткий набросок рекурсивного поиска в глубину:

private Node<T> searchAux(Node<T> node, T key){
    if(node == null) 
        return null;
    if (node.getElem() == key)
        return node;
    if (node.getChild() != null) {
        Node<T> foundNode = searchAux(node.getChild(), key);
        if (foundNode != null)
            return foundNode;
    } 
    return searchAux(node.getSibling(), key);
}

(Кстати, вам не нужны elses после returns.)

person themiurge    schedule 11.05.2017
comment
В порядке. Теперь вставка должна работать. Я проверил с различными деревьями. Тем не менее, методы глубины и степени не работают. - person Leo; 12.05.2017
comment
На первый взгляд, методы auxDepth никогда не посещают братьев и сестер. Попробуйте это исправить. - person themiurge; 12.05.2017
comment
Я изменил два метода, используя некоторое время, чтобы посетить всех братьев и сестер, и это работает. Большое спасибо за помощь! - person Leo; 12.05.2017