替换未排序树中的节点时的无限循环

时间:2015-05-11 08:43:47

标签: java recursion tree binary-tree

我在Java中做家庭作业,我必须创建一个以String作为数据值的未排序二叉树。然后我必须编写一个函数来替换与旧描述匹配的Node和任何重复Node与包含新描述的新对象。

以下是我正在使用的代码,包括导致无限循环的测试用例:

public class Node {

 private String desc;
 private Node leftNode = null;
 private Node rightNode = null;
 private int height;

 public Node(String desc) {
   this.desc = desc;
   height = 0; // assumes that a leaf node has a height of 0
 }

 public String getDesc() {
  return desc;
 }

 public Node getLeftNode() {
  return leftNode;
 }

 public Node getRightNode() {
  return rightNode;
 }

 public void setLeftNode(Node node) {
   ++height;
   leftNode = node;
 }

 public void setRightNode(Node node) {
   ++height;
   rightNode = node;
 }

 public int getHeight() {
   return height;
 }

 public int addNode(Node node) {
   if(leftNode == null) {
     setLeftNode(node);
     return 1;
   }
   if(rightNode == null) {
     setRightNode(node);
     return 1;
   }
   if(leftNode.getHeight() <= rightNode.getHeight()) {
     leftNode.addNode(node);
     ++height;
   } else {
     rightNode.addNode(node);
     ++height;
   }
   return 0;
 }

 public static void displayTree(Node root) {
   if(root != null) {
     displayTree(root.getLeftNode());
     System.out.println(root.getDesc());
     displayTree(root.getRightNode());
   }
 }

 public static Node findNode(Node current, String desc) {
   Node result = null;
   if(current == null) {
     return null;
   }
   if(current.getDesc().equals(desc)) {
     return current;
   }
   if(current.getLeftNode() != null) {
     result = findNode(current.getLeftNode(), desc);
   }
   if(result == null) {
     result = findNode(current.getRightNode(), desc);
   }
   return result;
 }

 public static void replaceNode(Node root, String oldDesc, String newDesc) {
   if(oldDesc == null || newDesc == null) {
     System.out.println("Invalid string entered");
     return;
   }
   boolean replacedAllNodes = false;
   while(replacedAllNodes == false) {
     Node replace = findNode(root, oldDesc);
     if(replace == null) { // No more nodes to replace
       replacedAllNodes = true;
       return;
     }
     replace = new Node(newDesc);
     root.addNode(replace);
   }
   return;
 }


 public static void main(String[] args) {
     Node root = new Node("test1");
     Node test_2 = new Node("test2");
     Node test_3 = new Node("test3");
     Node test_4 = new Node("test4");
     Node test_5 = new Node("test5");
     Node test_6 = new Node("test6");

     root.addNode(test_2);
     root.addNode(test_3);
     root.addNode(test_4);
     root.addNode(test_5);
     root.addNode(test_6);

     displayTree(root);
     replaceNode(root, "test4", "hey");
     System.out.println("-------");
     displayTree(root);
  }
}

在测试findNode方法并看到它返回正确的对象后,我意识到无限循环是由我的replaceNode方法引起的。我只是不确定它是如何造成它的。

我通过删除while循环让它与一个案例一起工作,但显然不会为重复项工作,所以我想知道如何用oldDesc删除节点并替换当可能有多个对象具有匹配的newDesc数据时,它包含一个包含oldDesc的新对象。

2 个答案:

答案 0 :(得分:1)

您永远不会在while循环中更改rootoldDesc

 while(replacedAllNodes == false) {
     Node replace = findNode(root, oldDesc);
     if(replace == null) { // No more nodes to replace
       replacedAllNodes = true;
       return;
  }
 replace = new Node(newDesc);
 root.addNode(replace);
}

如果你看

public static Node findNode(Node current, String desc) {
   Node result = null;
   if(current == null) {
     return null;
   }
   if(current.getDesc().equals(desc)) {
     return current;
   }
   if(current.getLeftNode() != null) {
     result = findNode(current.getLeftNode(), desc);
   }
   if(result == null) {
     result = findNode(current.getRightNode(), desc);
   }
   return result;
 }

如果if(current.getDesc().equals(desc))条件匹配,replace将始终为root,因此您陷入了while循环

<强>更新

  • 如果您不必更换整个节点,则可以在while循环结束时更新节点的说明。

而不是

 replace = new Node(newDesc);
 root.addNode(replace);

做类似的事情:

  root.setDesc(newDesc);

(当然你必须先创建一个setDesc()方法)

  • 如果你必须更换整个物体,你必须这样:

而不是

replace = new Node(newDesc);
root.addNode(replace);

做这样的事情:

replace = new Node(newDesc);
replace.setLeftNode(root.getLeftNode);
replace.setRightNode(root.getRightNode);

另外,您必须链接指向root的节点,使其指向replace,例如以下示例之一(取决于您的根当然是哪一方):

 nodeThatPointedToRoot.setLeftNode(replace);
 nodeThatPointedToRoot.setRightNode(replace);

答案 1 :(得分:0)

仔细查看你的代码,你不是要替换一个节点,你只是在树的边缘添加一个新节点,旧节点仍然存在,所以循环将永远存在,你可以添加一个临时变量一个自动增量功能,并指示您要更换的节点的级别,并且您发现它只是一次又一次地执行此操作,而不是执行所有这些过程如何只更换内部的描述节点?