【问题标题】:Binary search algorithm does not work properly - Java二分搜索算法无法正常工作 - Java
【发布时间】:2013-04-23 06:14:21
【问题描述】:

我想制作自己的二进制搜索算法来搜索 1 000 000 个元素的 ArrayList。我决定使用 do-while 循环进行搜索。我知道我可以使用 while() 循环。但是当我运行它时,需要很长时间才能找到数字。我猜想设置 ArrayList 的第一个和最后一个元素的值有问题。我的代码是

import java.util.*;

public class BinSearchAlg {
public static void main(String[]args){

    int first;
    int last;
    int median;//middle element of arraylist
    Long element;//element with median index
    Scanner scan = new Scanner(System.in);
    ArrayList<Long>list = new ArrayList();
    for(long l=0;l<1000000;l++){
        list.add(l);//list is sorted
    }
    first = 0;
    last = list.size();
    median = (last-first)/2;
    element = list.get(median);
    System.out.println("Choose the number: ");
    long l = scan.nextLong();
    do{
        if(element<l){
            first = median;
            median=(last-first)/2;
            element = list.get(median);
        }else{ //if(element>l){
            last = median;
        median = (last-first)/2;
        element = list.get(median);
        }
    }while(element!=l);
}
}

感谢您的帮助。

【问题讨论】:

    标签: java algorithm search binary do-while


    【解决方案1】:

    median 计算有问题:

    median=(last-first)/2;
    

    你应该这样做:

    median=(last+first)/2;
    

    在您拥有的当前代码中,当您在[10..16] 范围内搜索时,您的代码将尝试将目标与list.get(3) 的中值进行比较。

    可能还有另一个错误,但现在我将把这个留给你。提示:尝试[0, 1],这应该会暴露代码中的错误。

    【讨论】:

    • 还有first = median + 1; 而不仅仅是中位数。进一步while (first &lt; last).
    • @JoopEggen 是的,我没有给 OP 答案,但添加了一个提示。
    • @UmNyobe 嗯,有什么理由使用它吗?没有 set fst = med + 1 可以工作吗?
    • @ZiyaoWei 如果列表足够大,first + last 可以溢出。 (last - first)/2 + first,或者,正如 UmNyobe 所写,(first - last)/2 + last 不能溢出(对于 0 &lt;= first &lt;= last)。
    • @DanielFischer 啊,我明白了。谢谢! (虽然在溢出之前,大多数情况下内存可能先用完,我们总是可以使用long8)
    【解决方案2】:

    正如魏子尧回答的那样,您需要修复中位数。此外,您可能需要一个不同的循环退出条件 - 现在如果 l 不在列表中,您将获得一个无限循环。此外,您的if-else 必须是if-elseif-else - 目前如果l == element 则循环实际上会将其视为element &gt; l 并继续循环。

    【讨论】:

    • 好的,我在代码中使用了 median=((last-first)/2)+first。我还使用了 if(element>l){last = median-1; ...},然后我添加了 else if(element==l){break;} 和 else if(!list.contains(l)){break;} 并使用了 while(first
    • 取出!list.contains(1) - 这将对整个列表进行线性搜索。相反,将其替换为 else break; 以在找到元素后退出循环。
    • 完成。其余的代码对吗?二进制搜索现在有效吗?
    • 我认为你的代码应该返回一个布尔值来指示是否找到了元素。除此之外,它看起来已经准备好进行测试了。
    • 当我在列表范围内键入任何数字时,程序将在几毫秒后完成 - 此外我使用 System.currentTimeMillis() 方法来计算选择数字之间花费了多少时间并找到它。
    【解决方案3】:

    你可以直接使用 Collection 类的二分查找方法存在 java.util 包:-

    Collections.binarySearch(myList,key.get(i),new MyTransferObjectClass());
    

    和

    public class MyTransferObjectClass implements Comparator<MyTransferObjectClass>{
    
    @Override
        public int compare(MyTransferObjectClass o1, MyTransferObjectClass o2) {
                    //your logic for comparison
        }
    
    }
    

    既然可以使用可用的 API,为什么还要添加冗余代码。

    【讨论】:

      猜你喜欢
      • 2021-10-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-08
      • 2019-08-04
      • 2021-11-10
      • 2017-01-28
      • 2013-12-23
      相关资源
      最近更新 更多