我无法弄清楚为什么我的程序在条件语句中包含时会递归调用它自己。我正在进行一项演示快速选择的作业,一种快速排序的变体,可以让你找到第k个最小的元素。我不想太冗长所以我发布了问题代码希望我的解释可以给你一个我的目标的图片。
在下面的代码块中,k
是我想要找到的第k个元素。 l
是左边的下边界,所有数字都小于枢轴。如果k
位于下边界与l
之间,则可以搜索此方。
if (k-1<l) {
System.out.println("call quickSelect from " + begin + " to " + l);
if (l-1==begin)
{return begin;} //added to prevent random from throwing error
else {
depth++;
return quickSelect(arr,k,begin,l-1); }
}
quickSelect
时,我以递归方式调用l-1==begin
时出现问题。我得到错误Exception in thread "main" java.lang.IllegalArgumentException: bound must be positive
,因为我使用Java的随机对象(我用来在边界内找到一个数据透视)只能取一个正整数。所以这就是我添加条件语句l-1==begin
以防止在无效参数中调用quickSelect()的原因。但是,我得到了相同的错误!我很惊讶这是因为我认为if-else语句会处理这个异常。我真的很感激有关如何使用l-1==begin
调用quickSelect的任何想法。我已经为下面的程序包含了整个代码以获取更多详细信息,递归调用是针对底部的。
import java.util.Scanner;
import java.io.FileNotFoundException;
import java.io.File;
import java.util.ArrayList;
import java.util.Random;
import java.util.Collections;
public class quickSelect{
static int depth=0;
public static void main(String args[]) {
int totalDepth=0;
ArrayList<Integer>al = new ArrayList();
Scanner doc = new Scanner("");
// String smallFile = "proj2small.txt";
String smallFile = "proj2big.txt";
try {
File openSmallFile=new File(smallFile);
doc = new Scanner(openSmallFile);
} catch (FileNotFoundException e1 ) {
e1.printStackTrace();
}
while (doc.hasNext()) {
int f = doc.nextInt();
al.add(f);
}
int k=al.size()/2;
depth=0;
int p = quickSelect(al,k,0,al.size()-1);
System.out.println(k + "th element is " + p);
System.out.println(depth + " recursive calls ");
}
public static int quickSelect(ArrayList<Integer>arr,int k,int begin,int end) {
Random rand = new Random();
int range = end-begin;
int j = rand.nextInt(range);
//int equals=0;
int pivot = arr.get(j+begin);
System.out.println("pivot is " + pivot + " at index " + (j+begin));
int h=end-1;
int l=begin;
arr.remove(j+begin);//remove the pivot. Assume no duplicates are allowed
if (j+begin<k) {
k--; //shift k left one if index of pivot comes before it because we removed pivot
}
while (true) {
while (arr.get(l)<pivot) {
l++;
}
while(arr.get(h)>pivot) {
h--;
}
if(l>=h) {
break;
}
Collections.swap(arr, l, h);
l++;
h--;
}
//l is equal to the pivot?
//System.out.println("l is " + ((arr.get(l)==pivot)?"equal":"not equal") + " to the pivot");
System.out.println("k is " + k);
if (k-1<l) { //l-1 because left shift one after removal
System.out.println("call quickSelect from " + begin + " to " + l);
if (l-1==begin)
{return begin;} //added to prevent random from throwing error
else {
depth++;
return quickSelect(arr,k,begin,l-1); //array gets smaller k becomes smaller
}
}
else if (k-1==l) {
return pivot;
}
else {
System.out.println("call quickSelect from " + l + " to " + end);
if (end-1==l)
{return l;} //added to prevent random from throwing error
else {
return quickSelect(arr,k,l,end-1); //we removed the pivot so l is part of the high range
}
}
}
}
抱歉有趣的代码格式化。从日食中剔除不是一个好主意
答案 0 :(得分:5)
如果您的文件包含零或仅包含一个值,则al.size()的值将为0或1。
因此,k
将为0,无论哪种方式,因为0/2和1/2都等于0。
因此,当您将al.size()-1
作为end
传递给该方法时,在quickSelect()
的第一次运行中,它会传递0-1
,当然,{{1} }}
当您致电-1
时,会抛出nextInt(0, -1)
,并向您显示错误。