Java二分查找

发布于 2024-08-23 07:59:06 字数 968 浏览 6 评论 0 原文

尝试对 Book 对象的排序数组执行二分搜索。

它工作得不好,它返回某些对象的正确结果,但不是全部。

我在纸上完成了循环,似乎由于向上舍入 #.5 可能会遗漏一些数字。

有什么想法可以让这项工作发挥作用吗?

Book found = null;
    /*
     * Search at the center of the collection. If the reference is less than that,
     * search in the upper half of the collection, else, search in the lower half.
     * Loop until found else return null.
     */
    int top = numberOfBooks()-1;
    int bottom = 0;
    int middle;
    while (bottom <= top && found == null){
        middle = (bottom + top)/2;
        if (givenRef.compareTo(bookCollection.get(middle).getReference()) == 0) {
            found = bookCollection.get(middle);
        } else if (givenRef.compareTo(bookCollection.get(middle).getReference()) < 0){
            bottom = middle + 1;
        } else if (givenRef.compareTo(bookCollection.get(middle).getReference()) > 0){
            top = middle - 1;
        }
    }
    return found;

Trying to perform a binary search on a sorted array of Book objects.

Its not working well, it returns the correct results for some of the objects, but not all.

I went through the loop on paper and it seems that a number can get missed out due to rounding #.5 upwards.

Any ideas how to make this work?

Book found = null;
    /*
     * Search at the center of the collection. If the reference is less than that,
     * search in the upper half of the collection, else, search in the lower half.
     * Loop until found else return null.
     */
    int top = numberOfBooks()-1;
    int bottom = 0;
    int middle;
    while (bottom <= top && found == null){
        middle = (bottom + top)/2;
        if (givenRef.compareTo(bookCollection.get(middle).getReference()) == 0) {
            found = bookCollection.get(middle);
        } else if (givenRef.compareTo(bookCollection.get(middle).getReference()) < 0){
            bottom = middle + 1;
        } else if (givenRef.compareTo(bookCollection.get(middle).getReference()) > 0){
            top = middle - 1;
        }
    }
    return found;

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

硪扪都還晓 2024-08-30 07:59:06

给您一些建议:

  • 无需保留 Book 变量。在循环中,只需在找到书籍时返回该书,并在最后返回 null 即可。您还可以在 while 条件中删除对变量的布尔检查。

  • middle 变量的作用域可以在循环内部,不需要让它的生存时间更长。

  • 您执行了 bookCollection.get(middle).getReference() 三次。考虑创建一个变量,然后使用它。

  • middle = (bottom + top)/2 是二分搜索实现算法中的一个典型错误。甚至编写 Java Collection 类的 Joshua Bloch 也犯了这个错误(请参阅 这篇关于它的有趣的博客文章)。相反,请使用 (bottom+top) >>> 1,避免非常大的值的整数溢出(您可能不会遇到此错误,但这是原则性的)。

至于您的实际问题陈述,四舍五入将向下(整数除法),而不是向上。要解决该问题:

  • 您确定 numberOfBooks() 方法对应于您的集合的长度吗?
  • 您确定 compareTo() 方法对于您正在使用的类型按预期工作吗(在您的代码示例中,我们不知道 getReference() 返回类型是什么
  • )您确定您的集合已根据 getReference() 正确排序?
  • 最后,您确定使用 givenRef.compareTo(bookCollection.get(middle).getReference()) givenRef.compareTo(bookCollection.get(middle).getReference()) < 0 是正确的吗?在标准的二分搜索实现中,它会被颠倒,例如bookCollection.get(middle).getReference().compareTo(givenRef) bookCollection.get(middle).getReference().compareTo(givenRef) < 0 。这可能是唐罗比提到的,不确定。

无论如何,找到错误的方法是尝试不同的值,看看哪些输出正确,哪些输出不正确,从而推断出问题所在。如果您必须运行许多测试,您还可以使用调试器来帮助您逐步完成算法,而不是使用铅笔和纸。更好的是,正如 Donroby 所说,编写一个单元测试。

A couple suggestions for you:

  • there's no need to keep a Book variable. In your loop, just return the book when it's found, and at the end return null. And you can also remove the boolean check for the variable in the while condition.

  • the middle variable can be scoped inside the loop, no need to have it live longer.

  • you're doing bookCollection.get(middle).getReference() three times. Consider creating a variable and then using it.

  • the middle = (bottom + top)/2 is a classic mistake in binary search implementation algorithms. Even Joshua Bloch, who wrote the Java Collection classes, made that error (see this interesting blog post about it). Instead, use (bottom+top) >>> 1, to avoid integer overflow for very large values (you probably wouldn't encounter this error, but it's for the principle).

As for your actual problem statement, rounding would be downwards (integer division), not upwards. To troubleshoot the problem:

  • are you sure the numberOfBooks() method corresponds to the length of your collection?
  • are you sure the compareTo() method works as expected for the types you are using (in your code example we do not know what the getReference() return type is)
  • are you sure your collection is properly sorted according to getReference()?
  • and finally, are you sure that using givenRef.compareTo(bookCollection.get(middle).getReference()) < 0 is correct? In standard binary search implementations it would be reversed, e.g. bookCollection.get(middle).getReference().compareTo(givenRef) < 0. This might be what donroby mentions, not sure.

In any case, the way to find the error would be to try out different values and see for which the output is correct and for which it isn't, and thus infer what the problem is. You can also use your debugger to help you step through the algorithm, rather than using pencil and paper if you have to run many tests. Even better, as donroby said, write a unit test.

困倦 2024-08-30 07:59:06

Collections.binarySearch() 怎么样?

What about Collections.binarySearch()?

悲欢浪云 2024-08-30 07:59:06

JRL的所有建议都是对的,但真正的失败是你的比较颠倒了。

我自己并没有立即看到这一点,但是将代码复制到函数中(使用字符串而不是书籍),编写一些简单的 Junit 测试,然后在调试器中运行它们,这一切变得非常明显。

编写单元测试!

All of JRL's suggestions are right, but the actual fail is that your compares are reversed.

I didn't see this immediately myself, but replicating your code into a function (using strings instead of Books), writing a some simple Junit tests and then running them in the debugger made it really obvious.

Write unit tests!

鹿童谣 2024-08-30 07:59:06

我发现了问题。

事实证明,我正在对我的 bookCollection arrayList 进行二进制搜索,而不是我创建的新的 sroted 数组 -sortedLib。

我最后犯了一个愚蠢的错误,但感谢您的意见和建议!

I found the problem.

It turns out i was binary searching my bookCollection arrayList, and NOT the new sroted array i had created - sortedLib.

Silly mistake at my end, but thanks for the input and suggestions!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文