我正在为递归二进制搜索编写程序。我有一个输入文件,其中包含一系列已排序的数字,我将其添加到ArrayList中。程序搜索以查看用户输入给出的键是否在ArrayList中。
public static int binarySearch(int key, int median){
if(key == (int)array.get(median)){
return key;
}else if(key < (int)array.get(median)){
binarySearch(key,median-1);
}else if(key > (int)array.get(median)){
binarySearch(key,median+1);
}
return -1;
}
例如,假设键是90.我调试并将watch放在key和array.get(中位数)处。在单步执行程序之后,我发现即使key和array.get(中位数)等于90,程序也会继续循环而不返回密钥。我知道递归并不是理想的,但这是我需要使用的。
答案 0 :(得分:2)
这看起来不像正确的二进制搜索,因为二进制搜索使用分而治之的方法。您最初只划分一次列表,然后从那里检查每个元素。最好再次划分列表,依此类推,请参阅https://en.wikipedia.org/wiki/Binary_search_algorithm
无论如何,为了让你的代码运行,为什么你没有得到结果很可能是因为你没有返回递归的结果,而是返回-1。
删除return -1并在递归binarySearch调用之前设置一个返回值。当你找不到元素时,你会错过一个退出条件。
示例(仍然不是正确的二进制搜索):
public static int binarySearch(int key, int median){
if (median < 0 || median > array.size() - 1) { // element not found
return -1;
}
if (key == (int)array.get(median)){
return key;
} else if(key < (int)array.get(median)){
return binarySearch(key,median-1);
} else{
return binarySearch(key,median+1);
}
}
答案 1 :(得分:1)
如果您关心的是它是否在数据结构中......
public static boolean binarySearch(int key, int median){
if(key == (int)array.get(median)){
return true;
}else if(key < (int)array.get(median)){
return binarySearch(key,median-1);
}else if(key > (int)array.get(median)){
return binarySearch(key,median+1);
}
}
您的代码可以更好地编写,但复制到其中以了解其中的重要部分
答案 2 :(得分:1)
您应该像这样更改代码:
public static int binarySearch(int key, int median){
if(key == (int)array.get(median)){
return key;
}else if(key < (int)array.get(median)){
return binarySearch(key,median-1);
}else if(key > (int)array.get(median)){
return binarySearch(key,median+1);
}
return -1;
}
如果你这样做,你的递归会结束,但我会留给你测试你的二进制搜索代码。在此方法中有一些事情,比如你要忽略的起始索引和结束索引应该添加return语句,因为如果你没有控制移动到方法中的下一个语句,这是不合需要的。希望有所帮助!
答案 3 :(得分:1)
发布的代码不 a Binary Search,实际上是使用递归的线性搜索。二进制搜索将搜索空间分成两半每一步,二进制意味着“两半”在上下文中。结果是此线性搜索在O(n)中运行,而不是二进制搜索的预期O(lg n)边界
问题/问题(除了不是二进制搜索):
递归案例中的值丢失,因为它们本身并未返回。递归情况的结果必须以某种方式使用(或者为什么要调用该函数?)。在这种情况下,应该直接返回值,例如。 return binarySearch(..)
。这导致“继续循环而不返回密钥” - 它实际上 找到密钥,但丢弃了递归结果。
代码无法正确检测越界终端条件。当找不到密钥时,这可能导致IndexOutOfBoundsException。
如果没有其他逻辑,步骤左/右方法可能永远不会正确终止。例如,当列表是{1,3,5,7}并且所寻找的值是4时,原始代码将在索引1(值3)和2(值4)之间乒乓。这将导致抛出StackOverflowError。
返回密钥。这没有多大意义,因为密钥已经知道,它也可以防止-1被检测到。返回找到的索引,如果只需要存在测试,则返回布尔值。
花点时间了解并解决这些问题..如果需要,请继续阅读剧透。
考虑这个重写修复上面列出的问题。请注意,它仍然是过于复杂 1 ,同时仍采用较差的算法和O(n)性能。无论如何;
// By taking in the List we make this function universal and not
// dependent upon a static field. It should probably take in a List<Integer>
// but I don't know what the actual type of "array" is. A more advanced
// implementation would take in List<Comparable> and then be modified to work
// with any objects that correctly implement said interface.
public static int linearSearch(int key, List list, int index, int step) {
if (index < 0 || index >= list.size()) {
// Base case: not found, out of bounds
return -1;
}
int x = (int)list.get(index);
if (key < x && step <= 0) { // need to look left, NOT looking right
// Recursive case: look left, returning result
return linearSearch(key, list, index - 1, -1);
} else if (key > x && step >= 0){ // need to look right, NOT looking left
// Recursive case: look right, returning result
return linearSearch(key, list, index + 1, +1);
} else if (key == x) {
// Base case: found key, return index found
return index;
} else {
// Base case: key not equal, refusing to ping-pong
return -1;
}
}
然后考虑使用这个帮助器/包装器函数;
// Returns the index in "array" where key was found, or -1 if it was not found
public static int linearSearch(int key) {
// Have to start somewhere, might as well be the middle..
// ..but it does NOT make the time complexity any better
// ..and it is still NOT a Binary Search.
return linearSearch(key, array, array.size() / 2, 0);
}
1 或者,因为它是线性搜索,所以可以在没有额外的左/右移动的情况下重写它并且具有相同的复杂边界。 (将这个更简单的代码修改为recursive Binary Search也很简单。)
public static int linearSearch(int key, List list, int index) {
if (index >= list.size() {
// Base case: end of list
return -1;
}
int x = (int)list.get(index);
if (key < x) {
// Recursive case: not there yet, keep looking
return linearSearch(key, list, index + 1);
} else if (key == x) {
// Base case: found key, return index
return index;
} else { // -> key > x
// Base case: read past where the key would be found
return -1;
}
}
答案 4 :(得分:0)
这里是ArrayList<Integer>
的二进制搜索:)
public int binarySearch(List<Integer> list, int find) {
int mid = list.size() / 2;
int val = list.get(mid);
if (val == find) {
return val;
} else if (list.size() == 1) {
return -1;
}
return val > find ?
binarySearch(list.subList(0, mid), find) :
binarySearch(list.subList(mid, list.size()), find);
}