好的,所以在我的二分查找树中,我制作了一堆方法,但我目前正在测试其中的两个。其中一个将项目插入树中:
public void insert(String word) { //calls the insert method
root=insertItem(root, word);
}
protected TreeNode insertItem(TreeNode r, String word) { //inserts an item x into the tree
if(r==null){
r = new TreeNode(new WordRefs(word));
r.left = null;
r.right = null;
}
else if(word.compareTo(r.item.getWord()) < 0){
r.left = insertItem(r.left, word);
} else if (word.compareTo(r.item.getWord()) > 0){
r.left = insertItem(r.right, word);
}
return r;
}
另一个删除项目:
public void delete(String word) { //calls the delete method
root = deleteItem(root, word);
}
protected TreeNode deleteItem(TreeNode r, String word) { //deletes an item x from the BST
if (r == null){
return r;
}
if(word.compareTo(r.item.getWord()) < 0){
r.left = deleteItem(r.left, word);
} else if (word.compareTo(r.item.getWord()) > 0){
r.right = deleteItem(r.right, word);
} else if(r.left != null && r.right != null){
return deleteItem(r, word);
}
return r;
}
以下是测试这些方法的代码
public static void main(String args[]) { //the tests are in the main method
BSTRefBased t;
AbstractBinaryTree tt;
int i;
boolean result;
String message;
message = "Test 1: inserting 'word1' -- "; //tests the insert method first
t = new BSTRefBased();
try {
t.insert("word1");
result = t.getRootItem().getWord().equals("word1");
} catch (Exception e) {
result = false;
}
System.out.println(message + (result ? "passed" : "FAILED"));
message = "Test 2: inserting 'word1', 'word2', 'word3' -- ";
t = new BSTRefBased();
try {
t.insert("word1");
t.insert("word2");
t.insert("word3");
result = t.getRootItem().getWord().equals("word1");
tt = t.detachLeftSubtree();
result &= tt.getRootItem().getWord().equals("word2");
tt = t.detachRightSubtree();
result &= tt.getRootItem().getWord().equals("word3");
} catch (Exception e) {
result = false;
}
System.out.println(message + (result ? "passed" : "FAILED"));
message = "Test 3: deleting 'word1' -- "; //it then tests the delete method (note I keep getting failed for this one)
t = new BSTRefBased();
try {
t.delete("word1");
result = t.getRootItem().getWord().equals(null);
} catch (Exception e) {
result = false;
}
System.out.println(message + (result ? "passed" : "FAILED"));
message = "Test 4: deleting 'word2' 'word3' -- ";
t = new BSTRefBased();
try {
t.delete("word2");
t.delete("word3");
result = t.getRootItem().getWord().equals(null);
tt = t.detachLeftSubtree();
result &= tt.getRootItem().getWord().equals(null);
} catch (Exception e) {
result = false;
}
System.out.println(message + (result ? "passed" : "FAILED"));
}
对于我的输出,它表示测试1通过,但测试2,3和4都失败了。那么为什么测试2,3和4失败了呢?这就是我想要的删除方法:
delete(treeNode ,searchitem)
targetNode = search(treeNode ,searchItem)
if targetNode is null
return
P = parent node of target Node
if targetNode has no children
update ref in P that leads to targetNode
return
if targetNode has only one child C update ref in P that leads
to targetNode by overwriting that ref with C
(either left- or right-ref in P)
return
M = targetNode's inorder successor (i.e., left-most in-order
successor in targetNode's right subtree)
m = item in M
copy m into targetNode's item field
delete (treeNode, M)
return
答案 0 :(得分:1)
你的测试(测试1除外)看起来很棘手。
测试2断言BST的根为"word1"
,而左子树为"word2"
,右子树为"word3"
。这是......不太可能。
由于"word2"
和"word3"
来自 "word1"
后的,您的插入应该生成一个链接列表,{{ 1}}在根,"word1"
作为其右子(和"word2"
左子),然后null
作为"word3"
的右子。这不会通过测试2.(我说“应该”,因为一个单独的错误会使树更奇怪......请参阅本答复的后面部分。)
简而言之:除非你的BST在某个你没有告诉我们的地方进行了重新平衡,否则测试2是错误的。
测试3和4将从不传递,因为它们每次都会引发"word2"
---但你看不到它,因为它被捕获并被{{1价值。两个测试都试图从空树中删除一个或多个单词 - 他们不会先添加这些单词。然后,他们拨打NullPointerException
,这将始终返回全新BST的false
根。最后,他们在尝试在getRootItem
引用上调用null
方法时自杀。
但这并不意味着你的getWord
已经摆脱困境。我也发现了一些错误:
您的null
方法始终会添加到BSTRefBased
孩子,而不会insertItem
(拼写错误)。这会通过意外地切断合法的左子树来破坏你的BST ......有时候。
最后,我不确定r.left
是否会真正删除某个项目。 null,less-than和大于case的情况看起来还不错,但是......
r.right
因此,如果此deleteItem
有两个孩子,它会使用完全相同的参数调用// The "found the word" case...
} else if(r.left != null && r.right != null){
return deleteItem(r, word);
}
,这应该可以追索,直到您的堆栈空间用尽并崩溃。
根本没有处理只有一个孩子或零孩子的案例--- TreeNode
(当前deleteItem
,应该已被删除)而是返回,并且“删除了“字仍留在树上。