2012-11-02 41 views
1

我对自定义树有点麻烦。我正在编写一个“学习”动物的程序。让我们从节点开始。我从一个名为BTNode的类开始。它包含一个字符串值和一个“右”和“左”BTNode。然后,我将BTNode扩展到名为DecisionTreeNode的抽象类。 DecisionTreeNode由ThingNode和QuestionNode扩展。 Thing节点仅用于叶节点,其字符串值是动物的名称。 QuestionNode将持有区分动物的问题,并且应始终有两个子节点。Java自定义树节点交换

所以,这个想法是,它会通过询问用户提供的问题来学习。因此,它首先要求用户考虑动物,然后问“这是一个?”,如果我回答“否”,它会询问我的答案,并提出一个区分两者的问题。例如,我可以用一个thingNode(“mouse”)“种下”树,如果我想到一条鱼,那么我会回答它的第一个问题“不”,然后提供一个问题, “它生活在水中吗?”。现在下一次,它会开始问:“它生活在水中吗?”并且“是”会导致“是鱼”,而“否”会导致“是鼠标吗?”。

所以,我会在下面发布我的“学习”方法。我想我有一个引用问题。我将DecisionTreeNode传递给学习方法,但我对它做的更改不是级联备份。不知道我是否正确解释。该方法适用于第一次运行,您会看到将根节点从Thing更改为Question的位置,并将其子节点设置为两个动物。然而,这对于“当前”(传递到方法中的叶节点)不起作用,学习方法的最后一行是不按预期行事的行。

对不起,文本墙,让我知道你是否想要更多的代码发布或任何其他信息。 在此先感谢。

最初将“root”传递给play方法。

public static void play(DecisionTreeNode current) { 
    while(!current.isLeaf()) { 
     if(queryUser(current.getValue())) { 
      current = current.getYesLink(); 
     } 
     else { 

      current = current.getNoLink(); 
     } 
    } 
    System.out.println("Is it a " + current.getValue() + "?"); 
    if(!queryUser("Correct?")) { 
     learn(current); 
    } 
    else { 
     System.out.println("I win!"); 
    } 
} 




public static void learn(DecisionTreeNode current) { 
     String currentGuess; 
     String correctGuess; 
     String newQuestion; 
     ThingNode tempNode; 

     currentGuess = current.getValue(); 
     System.out.println("I give up, what animal were you thinking of?"); 

     correctGuess = stdin.nextLine(); 
     System.out.println("Please enter a yes or no question that distinguishes a " + correctGuess + " from a " + currentGuess +": "); 

     newQuestion = stdin.nextLine(); 

     tempNode = (ThingNode)current; 
     if(current == root) { 
      if(queryUser("")) { 
       root = new QuestionNode(newQuestion, tempNode, new ThingNode(correctGuess)); 
      } 
      else { 
       root = new QuestionNode(newQuestion, new ThingNode(correctGuess), tempNode); 
      } 
     } 
     else { 
      current = new QuestionNode(newQuestion, tempNode, new ThingNode(correctGuess)); 
     } 
    } 

回答

1

你的问题是在这里:

else { 
    current = new QuestionNode(newQuestion, tempNode, new ThingNode(correctGuess)); 
} 

当前是参数的方法。它是对值为的DecisionTreeNode 的引用。 设置current这里不会更改传递给该方法的current

您可以在current父传递给函数和调整其参考current或创建一个replace(Node, Node)方法,你可以调用像parent.replace(leaf, createNewLearnedNode(leaf))

+0

好吧,我认为这是问题,但我仍然不明白如何解决它。如果我理解正确,那么您的两条建议都需要我在播放方法的while循环期间跟踪两个节点(父 - 子)并将它们传递给它们。 –

+1

正确。您需要父级,因此您可以修改它并替换它指向的其中一个节点。您还需要用户启用的叶节点,以便您可以构建新的QuestionNode。 (或者你需要用户的是/否,所以你可以直接从父节点获得节点。) –

+0

想想我已经解决了,谢谢你们。 –