2016-11-16 3 views
0

Мне нужно зациклиться на дереве, чтобы получить все возможные пути, проблема в моем коде, что я получаю только первый путь!Получение всех возможных путей в древовидной структуре

пример: enter image description here

На рисунке, есть 2 дорожки т ручки: 1-2-3-4-5-6 и 1-2-3-7-8, но я не мог получите оба, я только что получил 1-2-3-4-5-6!

мой код:

В основной:

for (String key : synset.keySet()) { // looping in a hash of Concept and it's ID 
     System.out.println("\nConcept: " + key + " " + synset.get(key)); 
     List<Concept> ancts = myOntology.getConceptAncestors(myOntology.getConceptFromConceptID(synset.get(key))); // this function retreives the root of any node. 

     for (int i = 0; i < ancts.size(); i++) { 
      System.out.print(ancts.get(i).getConceptId() + " # "); 
      System.out.print(getChilds(ancts.get(i).getConceptId()) + " -> "); // here, the recursive function is needed to navigate into childs.. 
     } 
     System.out.println(""); 
    } 

Rec. Функция:

public static String getChilds(String conId) 
{ 
    List<Concept> childs = myOntology.getDirectChildren(myOntology.getConceptFromConceptID(conId)); // get all childs of a node 
    if(childs.size() > 0) 
    { 
     for (int i = 0; i < childs.size(); i++) { 
      System.out.print(childs.size() + " ~ " + childs.get(i).getConceptId() + " -> "); 
      return getChilds(childs.get(i).getConceptId()); 
     } 
    } 
    else 
     return "NULL"; 
    return "final"; 
} 
+0

Проблема заключается в том, что вы предоставляете только части информации, которые нам нужны, чтобы помочь вам. Не понимая, как ваше дерево действительно создано (представлено внутри), мы не можем сказать, почему ваш алгоритм неверен. Поэтому, пожалуйста, откиньтесь назад, обратитесь в справочный центр и прочитайте о http://stackoverflow.com/help/mcve, кроме того ... вы знаете, что есть много способов обхода деревьев? https://en.wikipedia.org/wiki/Tree_traversal – GhostCat

+0

Я ясно проиллюстрировал это требование. –

+0

из-за метода 'getChilds' возвращает' String'. Проблема, когда узел имеет более двух детей – Jerry06

ответ

0

Я действительно не видел достаточно вашего кода, чтобы использовать классы, которые вы определили. Поэтому я пошел писать собственное рабочее решение.

В следующем коде, проблема решается с помощью рекурсии:

public class TreeNode { 
    private String id; 
    private TreeNode parent; 
    private List<TreeNode> children; 

    public TreeNode(String id) { 
     this.id = id; 
     this.children = new LinkedList<>(); 
    } 

    public void addChild(TreeNode child) { 
     this.children.add(child); 
     child.setParent(this); 
    } 

    public List<TreeNode> getChildren() { 
     return Collections.unmodifiableList(this.children); 
    } 

    private void setParent(TreeNode parent) { 
     this.parent = parent; 
    } 

    public TreeNode getParent() { 
     return this.parent; 
    } 

    public String getId() { 
     return this.id; 
    } 
} 

public class TreePaths { 
    private static List<List<TreeNode>> getPaths0(TreeNode pos) { 
     List<List<TreeNode>> retLists = new ArrayList<>(); 

     if(pos.getChildren().size() == 0) { 
      List<TreeNode> leafList = new LinkedList<>(); 
      leafList.add(pos); 
      retLists.add(leafList); 
     } else { 
      for (TreeNode node : pos.getChildren()) { 
       List<List<TreeNode>> nodeLists = getPaths0(node); 
       for (List<TreeNode> nodeList : nodeLists) { 
        nodeList.add(0, pos); 
        retLists.add(nodeList); 
       } 
      } 
     } 

     return retLists; 
    } 

    public static List<List<TreeNode>> getPaths(TreeNode head) { 
     if(head == null) { 
      return new ArrayList<>(); 
     } else { 
      return getPaths0(head); 
     } 
    } 
} 

Чтобы использовать код выше, дерево должно быть построено с использованием TreeNode класса. Начните с создания головы TreeNode, затем добавьте к нему дочерние узлы по мере необходимости. Затем голова передается статической функции TreePaths getPaths.

После того, как getPaths проверит значение null, вызывается внутренняя функция getPaths0. Здесь мы следуем глубине первого подхода, пытаясь добраться до всех листовых узлов как можно скорее. Как только листовой узел будет найден, список, содержащий только этот листовой узел, будет создан и возвращен внутри коллекции списка. Родитель этого листового узла будет добавлен в начало списка, который снова будет помещен в список. Это произойдет для всех детей родителя.

В конце концов, все возможные пути будут объединены в единую структуру.Эта функция может быть проверена следующим образом:

public class TreePathsTest { 
    TreeNode[] nodes = new TreeNode[10]; 

    @Before 
    public void init() { 
     int count = 0; 
     for(TreeNode child : nodes) { 
      nodes[count] = new TreeNode(String.valueOf(count)); 
      count++; 
     } 
    } 

    /* 
    * 0 - 1 - 3 
    *  - 4 
    * - 2 - 5 
    *  - 6 
    *  - 7 - 8 
    *   - 9 
    */ 
    private void constructBasicTree() { 
     nodes[0].addChild(nodes[1]); 
     nodes[0].addChild(nodes[2]); 
     nodes[1].addChild(nodes[3]); 
     nodes[1].addChild(nodes[4]); 
     nodes[2].addChild(nodes[5]); 
     nodes[2].addChild(nodes[6]); 
     nodes[2].addChild(nodes[7]); 
     nodes[7].addChild(nodes[8]); 
     nodes[7].addChild(nodes[9]); 
    } 

    @Test 
    public void testPaths() { 
     constructBasicTree(); 
     List<List<TreeNode>> lists = TreePaths.getPaths(nodes[0]); 
     for(List<TreeNode> list : lists) { 
      for(int count = 0; count < list.size(); count++) { 
       System.out.print(list.get(count).getId()); 
       if(count != list.size() - 1) { 
        System.out.print("-"); 
       } 
      } 
      System.out.println(); 
     } 
    } 
} 

Это напечатает:

0-1-3 
0-1-4 
0-2-5 
0-2-6 
0-2-7-8 
0-2-7-9 

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

3

может быть, этот сегмент кода в getChilds() существует проблема:

for (int i = 0; i < childs.size(); i++) { 
     System.out.print(childs.size() + " ~ " + childs.get(i).getConceptId() + " -> "); 
     return getChilds(childs.get(i).getConceptId()); 
} 

for loop наклоняю играть роль, он всегда return getChilds(childs.get(0).getConceptId()); может быть, это не то, что вы хотите.

+0

да, это то, что я думал, но что альтернатива ..? –

+0

Я боюсь, что я не могу дать вам совет, основанный на вашем коде, потому что я не понимаю ваш код, потому что вы только немного представляете свой код. ** Но ** о требованиях, которые ** получают все возможные пути **, существует много решений, и ** mdewit ** дал возможное решение. –

+0

Вы возвращаетесь в первый проход через цикл for, используя только индекс 0. Используйте I вместо 0 и собираем все значения в списке, а затем возвращаем значение list.toString() - или что-то подобное, в зависимости от ваших потребностей. – Ignazio

0

Один простой способ.
Все, что вам нужно, это обход дерева и небольшой код.

  • Имейте список под названием tempPath. вы можете принять его как аргумент или глобальную переменную.
  • Проведите обход дерева (например, по порядку). Всякий раз, когда вы на узле, добавьте это в список tempPath в конце, и когда вы закончите с этим узлом, удалите узел с конца tempPath.
  • всякий раз, когда вы сталкиваетесь с листом, у вас есть один полный путь от корня до листа, который содержится в tempPath. вы можете распечатать или скопировать это значение списка в другую структуру данных.
Смежные вопросы