【问题标题】:Why does my BinarySearchTree implementation always report the inserted element as a duplicate?为什么我的 BinarySearchTree 实现总是将插入的元素报告为重复项?
【发布时间】:2014-01-10 16:52:12
【问题描述】:

我目前正在与 BST 合作,我的插入方法存在一些问题,尽管这对我来说似乎很合乎逻辑。经过调试,我发现我使用的变量的赋值有问题,就像每次我尝试插入一个节点时,它都会作为根插入,因此会打印出“不允许重复”。

为此,我分别使用 4 个类。以下方法位于扩展 BinaryTree 类的 BinarySearchTree 类中。在二叉树类中,我有一个受保护的 BinaryTreeNode 和其他用于树遍历的方法。

从 Main 调用方法:

    int value;
    System.out.println("Number of elements to be inserted: ");
    value = input.nextInt();

    for (int i = 0; i < value; i++) {
        System.out.print("Enter next element ");
        num = console.nextInt();
        x.setNum(num);

        tree.insert(x);
    }

问题在于 main 方法中的方法调用,而不是 inset 本身。

【问题讨论】:

  • 你在哪里打电话给insert?您实际上是在插入两个不同的 DataElement 对象吗?
  • @crush insert 在 main 方法中调用,我有一个 for 循环,要求用户插入插入树中的不同值。我实际上插入了 1 个 DataElement。
  • 我们可以看看那个方法吗?
  • 你认为什么是重复的?是对同一个对象的引用,还是两个具有相同值的对象?
  • 好吧,我正在尝试向树中插入不同的值,当我插入第一个值时,这不是问题,但是当我开始插入其余的值时,它会打印出重复消息。重复我的意思是在树中,没有 2 个节点可以具有相同的值

标签: java tree binary-search-tree


【解决方案1】:

问题出在几个地方。让我们从您的 main() 方法开始。

for (int i = 1; i <= numElt; i++) {
    System.out.print("Enter next element ");
    num = input.nextInt();
    x.setNum(num);

    tree.insert(x);
}

当您遍历元素时,您只是在更改单个 DataElement 对象 (x) 的值。

当你 insert 这个 DataElement 对象到你的 BST 时,你创建一个新的 BinaryTreeNode,然后设置一个对这个 DataElement 对象的引用。

BinaryTreeNode node = new BinaryTreeNode();
node.info = insertItem; //Reference set to the object here.

现在,暂时忽略 insert 方法的其余部分,然后返回循环。在下一次迭代中,您将更改 DataElement 对象的值。

但是您刚刚插入的 BinaryTreeNode 包含对同一 DataElement 对象的引用。因此,当您在新迭代中更改值时,最后一个 BinaryTreeNode 也会看到更改。

相反,您需要在循环的每次迭代中创建一个新的DataElement,并将其传递给insert() 方法。

所以,

for (int i = 1; i <= numElt; i++) {
    x = new DataElement(...); //... means whatever constructor parameters it takes.
    System.out.print("Enter next element ");
    num = input.nextInt();
    x.setNum(num);

    tree.insert(x);
}

这将为每个BinaryTreeNode 提供它自己的DataElement 对象实例。


检测重复项

等等,还有更多。您将重复项定义为具有相同值的对象,而不是相同的引用。所以还有很多工作要做。

在这里,在您的 insert 方法中,您检查 insertItem 是否与最后一个节点相同。

if (temp.info == insertItem) {
    System.out.println("We can't have duplicates!");
    return;
}

如果你想按值比较它们,你应该使用equals方法:

if (temp.info.equals(insertItem))

这应该通过值而不是通过引用来检查它们。

【讨论】:

  • 哇,这很有意义!所以你的意思是我在循环中创建一个新的 DataElement 以避免引用相同的 DataElement 对象?
  • @Sara 是的,没错。另外,不要忘记将 DataElement 对象按值与 equals 进行比较,否则您将无法检测到重复项。
  • @Sara 看起来你也可以使用 compareTo 方法来检查值,除了检查 != 0 而不是 &gt; 0&lt; 0
  • compareTo 用于帮助遍历,比如是遍历树的左侧还是右侧
  • 这真的很有帮助!谢谢!
【解决方案2】:

尝试改变

if (temp.info == insertItem)

if (temp.info.equals(insertItem))

if (temp.info.compareTo(insertItem) == 0)

【讨论】:

  • 如果temp.info == insertItem,那么它们是对同一个对象的引用,因此是“重复的”。
  • 这不会有什么不同,因为这实际上意味着同样的事情。
  • @Sara 这并不意味着同样的事情。第一个块比较对象引用。第二个块比较它们的值。但是,由于您正在设置引用并重用同一个对象,因此它们也将始终具有相同的值。
猜你喜欢
  • 2016-08-05
  • 1970-01-01
  • 2017-07-10
  • 1970-01-01
  • 2016-10-16
  • 1970-01-01
  • 2017-04-06
  • 1970-01-01
  • 2019-10-25
相关资源
最近更新 更多