我有这个方法,它使用递归来查找在二叉树中保存指定String
的节点。问题是它返回null
,它应该返回包含指定名称的节点,我不知道为什么。
以下是方法:
public Node getNode(Node currentNode, String name) {
Node retrieved = null;
if (currentNode.getName().equals(name)) { retrieved = currentNode; }
else
{
if (currentNode.right != null) {
getNode(currentNode.right, name);
}
if (currentNode.left != null) {
getNode(currentNode.left, name);
}
}
return retrieved;
}
任何有关可能出现问题的见解都将不胜感激。
答案 0 :(得分:1)
您需要捕获两个递归调用的返回值。否则你正在“无所事事”地进行递归并丢弃递归的结果。
public Node getNode(Node currentNode, String name){
Node retrieved = null;
if (currentNode.getName().equals(name)) { retrieved = currentNode; }
else
{
if (currentNode.right != null){
retrieved = getNode(currentNode.right, name);
}
if (retrieved == null && currentNode.left != null){
retrieved = getNode(currentNode.left, name);
}
}
return retrieved;
}
以下解决方案可以说是更好的风格,因为您可以对基本案例进行null
检查。请注意您不再需要检查currentNode.right != null
或currentNode.left != null
,因为在再一次递归步骤之后它们会被基本案例覆盖。
public static Node getNode(Node currentNode, String name){
// Base case: currentNode is null, nothing left to search
if (currentNode == null) {
return null;
}
Node retrieved = null;
if (currentNode.getName().equals(name)) {
retrieved = currentNode;
} else {
// Try to search right subtree
retrieved = getNode(currentNode.right, name);
// If not found in right subtree, then search left subtree
if (retrieved == null){
retrieved = getNode(currentNode.left, name);
}
}
return retrieved;
}
答案 1 :(得分:1)
getNode(currentNode.right, name);
您调用getNode(...)
方法但不对其执行任何操作。
如果您愿意使用googles Guava(我认为每个项目都必须拥有)和java 8,您可以执行以下操作:
public static final Traverser<Node> TREE_TRAVERSER =
Traverser.forTree((SuccessorsFunction<Node>) node ->
Stream.of(node.right, node.left)
.filter(Objects::nonNull)
.collect(Collectors.toList()));
然后在想要遍历树的地方调用它:
for (Node n : TREE_TRAVERSER.depthFirstPreOrder(root)) {
if (n.getName().equals("foo")) {
// todo: do stuff with node foo
}
}
java 8遍历树的方法是:
Iterable<Node> nodes = TREE_TRAVERSER.depthFirstPreOrder(root);
Optional<Node> result = StreamSupport.stream(nodes.spliterator(), false)
.filter(n -> n.getName().equals("foo")) // find node with name "foo"
.findAny(); // we assume there is <= 1 node, so we take any.
// node.isPresent() to check if you found a Node and result.get() to get the Node
好吧,Guava有一个名为Traverser<N>
的好类。你只需给它一个参数,即SuccessorsFunction<N>
。它接受任何对象N
并返回Iterable<? extends N>
,它们是子节点。
我们使用Stream
来执行此操作。首先,我们创建两个子节点的Stream
。然后,我们会将其过滤为仅Stream
nonNull
Node
个List
并将其收集到SuccessorsFunction<Node>
中(因为Iterable<Node>
想要返回{{1} }})。
此Traverser<N>
只需创建一次,因此我们将其设为public static final
。您现在可以选择迭代订单。我们选择depthFirstPreOrder
,它返回Iterable<N>
我们可以迭代
如果您之前没有听说过Stream
,我建议this turorial。
答案 2 :(得分:0)
我建议考虑tail recursions,因为这是一个主要因素:
public static Node getNode(Node currentNode, String name){
// Base case: currentNode is null, nothing left to search
if (currentNode == null) {
return null;
}
Node retrieved = null;
if (currentNode.name.equals(name)) {
return currentNode;
} else {
// Tail recursions
if(currentNode.left == null) {
return getNode(currentNode.right, name);
}
else if(currentNode.right == null) {
return getNode(currentNode.left, name);
}
// Non Tail recursion
else {
retrieved = getNode(currentNode.left, name);
// If not found in left subtree, then search right subtree
if (retrieved == null){
retrieved = getNode(currentNode.right, name);
}
}
}
return retrieved;
}
附件是在an online compiler上执行的完整代码:
public class MyClass {
static class Node {
public String name;
public Node left;
public Node right;
Node(String name) {
this.name = name;
right = null;
left = null;
}
@Override
public String toString() {
return "name = " + name + " hasLeft = " + (left != null) + " hasRight = " + (right != null);
}
}
static class Tree {
Node root;
public Node getRoot() {
return root;
}
private Node addRecursive(Node current, String value) {
if (current == null) {
return new Node(value);
}
if (value.compareTo(current.name) < 0) {
current.left = addRecursive(current.left, value);
} else if (value.compareTo(current.name) > 0) {
current.right = addRecursive(current.right, value);
} else {
// value already exists
return current;
}
return current;
}
public Tree add(String value) {
root = addRecursive(root, value);
return this;
}
public void traverseInOrder(Node node) {
if (node != null) {
traverseInOrder(node.left);
System.out.print(" " + node.name);
traverseInOrder(node.right);
}
}
public void traverseInOrder() {
traverseInOrder(root);
System.out.println("");
}
}
public static void main(String args[]) {
Tree tree = new Tree();
tree.add("a").add("ab").add("bbb").add("cc").add("zolko").add("polip").traverseInOrder();
Node found = getNode(tree.getRoot(),"vv");
System.out.println(found);
found = getNode(tree.getRoot(),"ab");
System.out.println(found);
found = getNode(tree.getRoot(),"polip");
System.out.println(found);
found = getNode(tree.getRoot(),"java");
System.out.println(found);
found = getNode(tree.getRoot(),"zolko");
System.out.println(found);
}
public static Node getNode(Node currentNode, String name){
// Base case: currentNode is null, nothing left to search
if (currentNode == null) {
return null;
}
Node retrieved = null;
if (currentNode.name.equals(name)) {
return currentNode;
} else {
// Tail recursions
if(currentNode.left == null) {
return getNode(currentNode.right, name);
}
else if(currentNode.right == null) {
return getNode(currentNode.left, name);
}
// Non Tail recursion
else {
retrieved = getNode(currentNode.left, name);
// If not found in left subtree, then search right subtree
if (retrieved == null){
retrieved = getNode(currentNode.right, name);
}
}
}
return retrieved;
}
}
主方法执行的输出:
a ab bbb cc polip zolko
null
name = ab hasLeft = false hasRight = true
name = polip hasLeft = false hasRight = false
null
name = zolko hasLeft = true hasRight = false