为什么这些BST方法都不起作用?

时间:2015-04-02 02:51:23

标签: java class testing methods binary-tree

好的,所以在我的二分查找树中,我制作了一堆方法,但我目前正在测试其中的两个。其中一个将项目插入树中:

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

1 个答案:

答案 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,应该已被删除)而是返回,并且“删除了“字仍留在树上。