树结构中的递归回溯

Posted

技术标签:

【中文标题】树结构中的递归回溯【英文标题】:Recursive Backtracking in tree structure 【发布时间】:2014-02-27 19:38:38 【问题描述】:

我有这个算法,我想使用递归回溯实现图形搜索。

首先是我的代码:

 public static boolean buildTree(GenericTreeNode<String> inputNode)

    while(!interruptFlag)
    
      try  Thread.sleep(200);  catch(InterruptedException e)  

      gui.frame.MainWindow.progress.setText("Iterations Deployment: " + c);
      gui.panel.ResultMatrix.setResult(mappingList);
      Multimap<String,String> openList = LinkedHashMultimap.create();

      openList = UtilityClasses.getOpenList.getOpenList(dataMap, ApplicationList,   HardwareList, mappingList);

    if(openList.isEmpty() && !mappingList.keySet().containsAll(XMLParser.ApplicationsListGUI))
            
                gui.frame.MainWindow.labelSuccess.setText("Mapping not succesful!");
                return false;

            
    if(openList.isEmpty() && mappingList.keySet().containsAll(XMLParser.ApplicationsListGUI))
            
                System.out.println(calculateOverallCost.getOverallCosts());
                System.out.println("Mapping done:" + " " + mappingList);
                gui.panel.ResultMatrix.setResult(mappingList);

                return true;
            

    if(!openList.isEmpty() && (!mappingList.keySet().containsAll(XMLParser.ApplicationsListGUI)))
        

          for(String s : openList.keySet())
          
              for(String h : openList.get(s))
              
                GenericTreeNode<String> child = new GenericTreeNode<String>(s + ":" + h); 
                inputNode.addChild(child);
                child.setCosts(UtilityClasses.CostFunction.calculateCostFunction(s, h));
              
          
          List<GenericTreeNode<String>> childlist = inputNode.getChildren();  
          Collections.sort(childlist);

          for(int i = 0; i < childlist.size() ; i++)
                        
             inputNode = childlist.get(i);
                     // do something      
             if (buildTree(inputNode))
                 
                 return true;
                 
             else
             
            // undo something
             

         

这就是我到目前为止的代码。它在每一步中构建树。树中的每个节点都是一个可能的解决方案,由启发式成本函数排序。前 2 个 if 子句是终止和返回的条件。如果有解决方案,它会发现它非常顺利。但是如果没有快速的解决方案,我需要撤消最后一步并尝试其他一些组合。在最坏的情况下,应该测试每个组合。

childlist 包含每个子节点,按其成本函数排序。将选择成本函数最小的那个进行扩展。构建树是递归完成的,但是回溯有问题。我没有让搜索后退一步并尝试第二好的节点,依此类推。该图每一步都会使用新计算的openList 进行扩展。如果有帮助,我保存了对父节点的引用。

openlist 是一个列表,其中包含所有可能的下一步 -> 节点。

也许这张图片将有助于更好地解释我的问题: 这或多或少是我想要实现的搜索。但是我到现在为止的代码,无论是否找到解决方案,都停留在休假结束时。我尝试了很多不同的方法,但这种回溯似乎不起作用,因为我的问题或至少我无法继续。

【问题讨论】:

此代码没有提供足够的信息来解决您的问题。请提供此函数的代码:UtilityClasses.getOpenList.getOpenList(dataMap, ApplicationList, HardwareList, mappingList) 另外请说明在mappingList 中存储的内容并提供任何修改其内容的代码。 你提到的类返回openList,其中包含一步树的节点。 MappingList 包含选择用于扩展的所有节点。当代码回溯时,它应该从 mappingList 中删除节点。 在您提供的代码中,没有从 mappingList 中删除任何元素。你的代码也很复杂。为了使其更具可读性和更易于调试,请尝试在代码中将当前组合在一个函数中的三种不同的东西分开:构建树、树遍历和 gui 交互。也尽量不要使用任何静态函数调用或实例变量。 【参考方案1】:

如果我理解正确,这需要pre-order tree vist。

我省略了一些细节,但我认为这段代码会对你有所帮助(我没有测试过):

public static boolean buildTree(GenericTreeNode<String> inputNode) 
    if (interruptFlag) 
        // search was interrupted
        // answer has not be found yet
        return false;
    

    boolean something = openList.isEmpty() && !mappingList.keySet().containsAll(XMLParser.ApplicationsListGUI);
    if (something) 
        // ... Mapping not succesful!
        // answer can't be found
        return false;

    

    boolean answerFound = openList.isEmpty() && (mappingList.keySet().containsAll(XMLParser.ApplicationsListGUI));
    if (answerFound) 
        // ...
        return true;
    

    // answer has not been found
    // visit each children
    // order children list by cost
    // ...
    List<GenericTreeNode<String>> childlist = // ...
    Collections.sort(childlist);

    for (int i = 0; i < childlist.size(); i++) 
        inputNode = childlist.get(i);
        // do something
        boolean childHasAnswer = buildTree(inputNode);
        if (childHasAnswer) 
            // answer was found
            return true;
         // else: our children do not have the answer
    

    // neither we or our children have the answer, let's go to the parent
    return false;

我主要删除了第一个while,删除了最后一个else。

【讨论】:

这不是 100% 正确的答案,但给了我正确解决方案的一个很好的提示。谢谢。

以上是关于树结构中的递归回溯的主要内容,如果未能解决你的问题,请参考以下文章

递归与回溯

二叉树专题

JavaScript中嵌套对象结构中的递归树搜索

树 的作业

决策树的几种类型差异及Spark 2.0-MLlibScikit代码分析

java递归与反向递归(逆向递归)查询树tree结构根据关键字过滤数据