我是Java的新手,刚刚开始学习一些简单的数据结构和算法。我一直在尝试实现二进制搜索功能,但是我一直收到堆栈溢出错误,而且我不知道它从哪里来。
public class BinarySearch {
public static void main (String[]args){
BinarySearch bs = new BinarySearch();
int array [] = {1, 8, 6, 91, 52, 74, 5, 9};
int length = array.length;
bs.sort(array, 0, length-1);
bs.print(array);
System.out.println();
System.out.println(bs.binarySearch(array, 0, length-1, 5));
}
public int binarySearch(int array [], int low, int high, int desired){
int pivot = array[(low+high)/2];
if(desired<pivot){
binarySearch(array,low,pivot, desired);
}else if(desired>pivot){
binarySearch(array, pivot+1, high, desired);
}else {
return (low+high)/2;
}
// if element not present in array
return -1;
}
答案 0 :(得分:3)
您的代码有几个问题。
您不会返回递归调用的结果。添加return
。
if(desired<pivot){
return binarySearch(...);
}else if(desired>pivot){
return binarySearch(...);
}
不要将要检查的索引与要检查的枢轴值混合在一起。计算索引并单独使用。另外,在重复出现低电平时,使用index - 1
代替index
作为high
,以免将来考虑使用当前索引。
int index = (low+high)/2;
int pivot = array[index];
if(desired<pivot){
return binarySearch(array,low,index - 1, desired);
}else if(desired>pivot){
return binarySearch(array, index+1, high, desired);
}else {
return index;
}
如果您的低值大于您的高值,则找不到该值。这是您的基本情况,不会在底部返回-1
(无论如何现在是无法访问的代码,因为上面的每个逻辑分支都已返回一个值)。将其放在您当前的if
上方。
int index = (low+high)/2;
int pivot = array[index];
if (low > high)
return -1;
if ...
假设您的sort
正常工作,以上更改应正确返回元素的索引;如果找不到,则返回-1
。
答案 1 :(得分:1)
运行此命令时,我得到indexoutofboundsexception
,因为在这些行中:
int pivot = array[(low+high)/2];
if(desired<pivot){
binarySearch(array,low,pivot, desired);
}
您将pivot
作为最高点,可以是array
中的任何数字。在此摘录的第一行中,您将称为high + low
的索引,该索引可以是array
中的任何数字加上您最初作为low
传递的任何数字。因此,在此示例中,您可以调用0 + 92
的{{1}}索引。
对于array
,它在这一行:
StackOverflow
这里您在递归调用中传递了完全相同的参数,因此,如果它进入if(desired<pivot){
binarySearch(array,low,pivot, desired);
}
循环的此分支,它将继续调用递归调用,直到它们中的太多进入堆栈为止堆栈溢出错误
答案 2 :(得分:1)
BinarySearch 用于已对数组本身进行排序(按顺序)的情况,这是 BinarySearch 的基础,并且您已经进行了排序部分。
但是,您的解决方案中存在两个明显的问题:
pivot
,您在此处使用元素作为索引; mid
之后应忽略if (desired < pivot)
; 此外,您应该尝试使用low + (high-low) / 2
来获取中间索引(当数组的大小足够大时low + high
会炸毁int
),然后获取{ {1}}可以避免整数溢出,这也是获取中间索引的一种更好的做法。
pivot = array[mid]
输出:
public class BinarySearchBasic {
public static void main(String[] args) {
BinarySearchBasic bs = new BinarySearchBasic();
int array[] = {1, 8, 6, 91, 52, 74, 5, 9};
int length = array.length;
Arrays.sort(array);
System.out.println(Arrays.toString(array));
System.out.println();
System.out.println(bs.binarySearch(array, 0, length - 1, 5)); // miss;
System.out.println(bs.binarySearch(array, 0, length - 1, 8)); // hit!
}
public int binarySearch(int array[], int low, int high, int desired) {
int mid = low + (high - low) /2;
int pivot = array[mid]; // get the middle element;
if (desired < pivot) {
binarySearch(array, low, mid - 1, desired); // since it's already smaller, use mid - 1 directly;
} else if (desired > pivot) {
binarySearch(array, mid + 1, high, desired); // same reason, use mid + 1 directly to skip mid;
} else {
return mid; // bingo!
}
return -1; // not found;
}
}
答案 3 :(得分:1)
您没有基本情况。递归需要一个基本案例来知道何时停止递归。无限递归的结果是StackOverflowException
,因为您正在调用且正在调用但未返回。您将要进行无限递归。二进制搜索的基本情况是hi
小于lo
时。
您还希望将左呼叫从low
更改为m-1
,而不是旋转,因为两端的边界都包含在内。
您还使用枢轴 VALUE 作为索引!而不是中间的 INDEX :
binarySearch(array, low, pivot-1, desired);
应该是:
binarySearch(array, low, m-1, desired);
方法:
public int binarySearch(int array [], int low, int high, int desired) {
// Not found
if (high < low)
return -1;
// Middle index
int m = low + (high - low) / 2;
// Middle value
int pivot = array[m];
if (desired < pivot)
binarySearch(array, low, m-1, desired);
else if (desired > pivot)
binarySearch(array, m+1, high, desired);
else
return m;
}