我对自定义树有点麻烦。我正在编写一个“学习”动物的程序。让我们从节点开始。我从一个名为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));
}
}
好吧,我认为这是问题,但我仍然不明白如何解决它。如果我理解正确,那么您的两条建议都需要我在播放方法的while循环期间跟踪两个节点(父 - 子)并将它们传递给它们。 –
正确。您需要父级,因此您可以修改它并替换它指向的其中一个节点。您还需要用户启用的叶节点,以便您可以构建新的QuestionNode。 (或者你需要用户的是/否,所以你可以直接从父节点获得节点。) –
想想我已经解决了,谢谢你们。 –