防止将重复项添加到二进制搜索树中

时间:2015-02-09 21:14:00

标签: java recursion nodes binary-search-tree

这是作业。请不要只给我代码。

任务是实施BST使用的几种方法;其中包括add(T data)remove(T data)。我能够成功实施它们。

以下是两种方法的指导原则:

  • public void add(T data)
    • 如果数据已经在树中,则什么都不做(没有重复)
    • 必须是递归的(我创建了一个辅助函数)
  • public T remove(T data)
    • 如果数据不在树中,throw new java.util.NoSuchElementException()
    • 必须是递归的(我创建了一个辅助函数)

我最初对其进行了编码,因此使用contains(T data)方法检查如何添加/删除数据。我发现我不能使用contains()方法来执行此操作,并且我必须以其他方式实现它。

从概念上讲,我理解我需要从根本上检查我们是否在没有叶子的父节点上。但是,我并不完全确定 如何实现这些检查。

例如,以下是我的add()方法:

@Override
public void add(T data) {
    if (data == null) {
        throw new IllegalArgumentException("Data is null");
    }
    //FIXME don't use the contains() method
    if (root == null) {
        BSTNode<T> node = new BSTNode<>(data);
        root = node;
    } else {
        addRec(root, data);
    }
    size++;
}

/**
 * Helper method to recursively add data to the BST
 * @param node is the node we're currently at
 * @param data is the data we're adding to the BST
 * @return node that we added
 */
private BSTNode<T> addRec(BSTNode<T> node, T data) {
    //This if-statement isn't correct
    if (compare(data, node.getLeft().getData()) == 0
        || compare(data, node.getRight().getData()) == 0) {
        return node;
    }

    if (node == null) {
        return new BSTNode<T>(data);
    }
    if (compare(data, node.getData()) == 0) {
        return node;
    } else if (compare(data, node.getData()) < 0) {
        node.setLeft(addRec(node.getLeft(), data));
    } else if (compare(data, node.getData()) > 0) {
        node.setRight(addRec(node.getRight(), data));
    }
    return node;
}

@Override
public boolean contains(T data) {
    if (data == null) {
        throw new IllegalArgumentException("Data is null");
    }
    if (root == null) {
        return false;
    } else {
        return containsRec(root, data);
    }
}

/**
 * Helper method to recursively check if the BST contains the data
 * @param  node is the node we're currently at
 * @param  data is the data we're looking for
 * @return boolean if the data was found
 */
private boolean containsRec(BSTNode<T> node, T data) {
    if (node == null) {
        return false;
    } else if (compare(data, node.getData()) == 0) {
        return true;
    } else if (compare(data, node.getData()) < 0) {
        return containsRec(node.getLeft(), data);
    } else if (compare(data, node.getData()) > 0) {
        return containsRec(node.getRight(), data);
    } else {
        return false;
    }
}

private int compare(T a, T b) {
    return a.compareTo(b);
}

如果我能弄清楚这一点,我很确定修复remove()方法几乎是一样的。


失败的测试(有几个)

@Test
public void testAddDuplicate() {
    // setup
    makeTree();

    // add duplicates
    bst.add(bst.getRoot().getData());
    bst.add(bst.getRoot().getLeft().getData());
    bst.add(bst.getRoot().getRight().getData());

    // check size
    assertEquals(9, bst.size());
}

2 个答案:

答案 0 :(得分:2)

实施遍历二叉树的三种方式的 一个 ,即在订单,预订单或后订单中。

利用此方法确定您的树是否包含给定项目。如果添加,您不需要做任何事情。如果删除,您可以从树中删除该节点。

答案 1 :(得分:1)

if (root == null) {
    BSTNode<T> node = new BSTNode<>(data);
    root = node;
} else {
    addRec(root, data);
}
size++;

在此代码中,无论是否找到重复元素或者树是否实际更改,都会增加size。因此,单元测试(正确地)识别树的size已经改变,即使树只有正确数量的元素。

只有在实际向树中添加新节点时才应增加size