【问题标题】:Need help reviewing my Binary Search program需要帮助查看我的二分搜索程序
【发布时间】:2013-05-07 23:14:04
【问题描述】:

我正在尝试在 Java 中实现二进制搜索,但我的代码存在一些问题。如果我要查找的元素存在于数组中,它会起作用。如果没有,程序不会打印错误消息。我的意思是——

当我运行我的代码时 - 这是输出 -

Please enter array size
2
Please enter element 0
3
Please enter element 1
4
Sorted array elements[3, 4]


Please enter the element you want to find in the array
3
Match 3 found at index 0

但是,如果我查找数组中不存在的元素,则程序不会进入 else 循环,并打印错误消息 - 而是这样做 -

Please enter array size
2
Please enter element 0
3
Please enter element 1
4
Sorted array elements[3, 4]


Please enter the element you want to find in the array
2
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -1
    at arraysPract.BinarySearch.findElement(BinarySearch.java:82)
    at arraysPract.BinarySearch.main(BinarySearch.java:54)

这里是代码 -

package arrays;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;

public class BinarySearch {
    static int[] binaryArr = null;

    public static void main(String[] args) {
        BufferedReader br = null;
        String size = "";

        try {
            System.out.println("Please enter array size");
            br = new BufferedReader(new InputStreamReader(System.in));
            size = br.readLine();
            if (size == null) {
                System.out.println("Size can't be null");
                return;
            }
            int ipSize = Integer.parseInt(size);
            binaryArr = new int[ipSize];
            String entry = "";
            for (int i = 0; i < ipSize; i++) {
                System.out.println("Please enter element " + i);
                entry = br.readLine();
                if (entry == null) {
                    System.out.println("Value can't be null");
                    return;
                }
                int arrEntry = Integer.parseInt(entry);
                binaryArr[i] = arrEntry;
            }

            Arrays.sort(binaryArr);
            System.out.println("Sorted array elements"  + Arrays.toString(binaryArr));
            System.out.println("\n");

            System.out.println("Please enter the element you want to find in the array");
            String findArrayElement = br.readLine();
            int find = Integer.parseInt(findArrayElement);      
            boolean elementExists = Arrays.asList(binaryArr).contains(find);            
            if (elementExists==false) {             
                findElement(binaryArr, find);
            }

            else {
                System.out.println("Element does not exist. Please try again");
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static int findElement(int[] test, int keyElement) {
        boolean flag = true;
        int i = 0;
        for (i = test.length / 2; i >= 0 && i < test.length;) {
            if (keyElement == test[i]) {
                flag = false;
                break;
            } else if (keyElement > test[i]) {
                i++;
                if (keyElement == test[i]) {
                    flag = false;
                } else {
                    flag = true;
                }
            } else if (keyElement < test[i]) {
                i--;
                if (keyElement == test[i]) {
                    flag = false;
                } else {
                    flag = true;
                }
            }
        }

        if (flag == false) {
            System.out.println("Match " + keyElement + " found at index " + i);
        }
        return i;
    }
}

如果我忽略了一些明显的错误,请有人指导我?

此外,这篇文章有几个可能的重复项 - Binary search in javaBinary search in java 等。我只需要帮助来审查我的代码,而不是实现程序:)

【问题讨论】:

  • 也许这更适合codereview.stackexchange.com
  • 这不是一个开始的二进制搜索,我建议你阅读 Arrays.binarySearch 的代码,看看它是什么样子的。它也短得多。 ;)
  • 我想实现自己的算法,所以我没有使用 Arrays.binarySearch。为什么说它不是二分查找?
  • 这不是二分搜索,因为您只是在遍历数组的上半部分或下半部分。这提供了 O(n/2) 的性能,或者换句话说 O(n)。二分搜索不断将它正在搜索的区域减半,这提供了 O(log n)。
  • @user2341013 这不是二分搜索,因为它不具有时间复杂度为 O(log(n)) 的特性——也就是说,它不是平均只多走一步来搜索两倍大的数组,平均需要两倍的时间(因为您是在进行线性搜索,而不是重复地将数组一分为二)

标签: java


【解决方案1】:

这不是二分搜索,您应该继续将索引除以二(或递归,在递归版本中)。相反,您正在对数组的两半进行复杂的线性搜索(线性搜索,因为索引在每一步中递增/递减 1,一个常数)。

无论如何,2 的问题在于它小于数组的最小元素,因此 i 会递减直到达到 0(第一个元素);此时,执行此行:

i--;

然后,调用test[i] 进行比较。但是i 将是-1,超出范围。测试后致电i--,而不是之前。

请扔掉你的代码,仔细阅读this good reference并正确实现二分搜索:如果你了解二分搜索的工作原理,代码非常简单。

编辑:查看here 进行线性搜索。

【讨论】:

  • 我会的。谢谢你告诉我。
  • 其实你没有。我的意思是:i.stack.imgur.com/uqJeW.png 由于您在这里似乎是新人,因此接受答案可以在“最新”问题视图中进行适当区分,并清楚地表明问题已解决。
  • 那么我的程序是线性搜索吗?
  • 你能检查我现在有没有?
  • 是的,很好。继续编码! :)
【解决方案2】:

无论您是否使用正确的算法,您的代码抛出 ArrayOutOfBoundsException 的原因是您在增加或减少 i 将标志设置为 false 的情况下继续增加或减少 i。如果进入循环迭代找到匹配项,则跳出循环;在其他两种情况下,您递增/递减循环,然后再次检查,但如果标志更改,您不会中断。在这种情况下,最好使用 while 或 do/while 循环。如果您在递增或递减之后删除第二个检查,您将实现您想要做的事情。

就算法而言,您不是在增加数组索引,而是在每次通过数组时将搜索范围减半。

从中得到的有用之处在于,异常和堆栈跟踪会告诉您出了什么问题(数组索引为 -1)以及它发生的位置、方法和行(在 ArraysPract.BinarySearch.findElement(BinarySearch.java: 82)

【讨论】:

    【解决方案3】:

    让我试着弄清楚二叉树是什么,希望它能让你的代码更容易一些。

    二分搜索可以被认为是散布在树中的一堆变量。例如,如果树的根或树顶的数字为 8,则落在左侧的所有内容都小于或等于 8,而从该节点右侧分支的所有内容都更大。

    【讨论】:

      猜你喜欢
      • 2020-08-03
      • 2017-03-15
      • 2022-01-25
      • 2014-05-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-11
      • 2017-06-07
      相关资源
      最近更新 更多