Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/388.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/powershell/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 选择秩算法_Java_Algorithm - Fatal编程技术网

Java 选择秩算法

Java 选择秩算法,java,algorithm,Java,Algorithm,下面是选择秩算法的实现,该算法用于查找数组中第k个最小元素之前的元素。有时该程序工作正常,但有时由于堆栈溢出错误(代码段下面的错误)而失败 公共静态整数兰德(整数左,整数右){ 返回left+(int)(Math.random()*(double)(right-left)); } 公共静态int-rank(int[]数组,int-left,int-right,int-rank){ int pivot=rand(左、右); int leftend=partition(数组,左,右,数组[pivot

下面是选择秩算法的实现,该算法用于查找数组中第k个最小元素之前的元素。有时该程序工作正常,但有时由于堆栈溢出错误(代码段下面的错误)而失败

公共静态整数兰德(整数左,整数右){
返回left+(int)(Math.random()*(double)(right-left));
}
公共静态int-rank(int[]数组,int-left,int-right,int-rank){
int pivot=rand(左、右);
int leftend=partition(数组,左,右,数组[pivot]);
int size=leftend-left+1;
如果(大小==排名+1){
for(int i=0;i秩)
返回秩(数组、左、左端、秩);
else返回秩(数组,左端+1,右,秩-大小);
}   
公共静态int分区(int[]数组、int左、int右、int轴){
while(true){
while(左枢轴)
对--;
如果(左>右)
返回左-1;
int temp=数组[左];
数组[左]=数组[右];
数组[右]=温度;
}
}
错误:

Exception in thread "main" java.lang.StackOverflowError
    at java.util.Random.nextDouble(Random.java:409)
    at java.lang.Math.random(Math.java:712)
    at mod.rand(mod.java:12)
    at mod.rank(mod.java:16)
    at mod.rank(mod.java:25)

我想可能是rand()导致了这个问题,但我不确定。我也不知道如何解决它。

递归永远不会结束,不是因为输入,而是因为使用了random, 从理论上讲,random每次都可以给你相同的数字。 例如,更改为:

public static int rand(int left, int right)
{
    return right - 1;
}
在输入时尝试:

int[] array= {1,2,11,67,35};
rank(array, 0, 4, 2);

在这个输入中,您将得到
java.lang.StackOverflowerError
,因为递归永远不会结束。

StackOverflower的Javadoc说:

由于应用程序递归太深而发生堆栈溢出时引发

由于默认限制非常高,StackOverflowerError通常表示无限递归

要有效诊断此类错误,请使用具有调试支持的体面IDE,为
StackOverflowerError
设置异常断点,运行程序,并在达到断点后检查堆栈中的局部变量

在这里,我们得到以下堆栈:

Random.nextDouble() line: 444 [local variables unavailable] 
Math.random() line: 716 
Test.rand(int, int) line: 5 
Test.rank(int[], int, int, int) line: 9 
Test.rank(int[], int, int, int) line: 18    
Test.rank(int[], int, int, int) line: 18    
Test.rank(int[], int, int, int) line: 18    
Test.rank(int[], int, int, int) line: 18    
Test.rank(int[], int, int, int) line: 18    
Test.rank(int[], int, int, int) line: 18    
Test.rank(int[], int, int, int) line: 18    
Test.rank(int[], int, int, int) line: 18    
Test.rank(int[], int, int, int) line: 18    
Test.rank(int[], int, int, int) line: 18    
Test.rank(int[], int, int, int) line: 18    
Test.rank(int[], int, int, int) line: 18    
Test.rank(int[], int, int, int) line: 18    
...
rank似乎从第18行无限调用自己。让我们通过检查局部变量来验证这一点。对于第18行的最顶层堆栈帧:

left    97  
right   107 
rank    5   
pivot   102 
leftend 107 
size    11
对于下面的一个:

left    97  
right   107 
rank    5   
pivot   101 
leftend 107 
size    11  
下面的那个

left    97  
right   107 
rank    5   
pivot   105 
leftend 107 
size    11
事实上,
left
right
在这些堆栈帧中是相同的,即算法停止了进展。我们还看到,即使每次选择不同的轴索引,
leftend
仍然等于
right

查看有问题的数组索引,我们可以看到:

[97]    10  
[98]    10  
[99]    10  
[100]   10  
[101]   10  
[102]   10  
[103]   10  
[104]   10  
[105]   10  
[106]   10  
[107]   10  
看起来您没有处理子范围中所有元素正确相等的特殊情况

实际上,在这种情况下,
partition
将始终返回
right
,而
rank
将使用相同的参数调用自身,无限递归

带回家的信息:

  • 在出现故障时检查程序的状态(例如使用调试器和断点)对于查找错误非常有用
  • 不要忽视角案

  • 我假设您希望您的
    rand
    方法返回一个介于左(包括)和右(包括)之间的数字。但是,Math.random()方法返回一个介于0.0(包括)和1.0(排除)之间的数字。因此,在正在计算的子数组的大小为2的情况下,(即:左=4,右=5),因此,
    rand
    函数只能返回4。 尝试在
    rand
    函数中更改此行,以确保它可以包含上限:

    返回left+(int)(Math.random()*(double)(right-left));

    为了


    返回left+(int)(Math.random()*(double)(right-left+1));

    不,可能是
    秩(
    这就是问题所在。可能你的递归永远不会ends@Kostia你的意思是肯定的,你能给出一个它失败的例子吗,这将使它更容易修复,而不是找到我们自己的例子调用
    System.out.println(“left=“+left+”\tright=“+right+”\tleftend=“+leftend”)
    紧跟在
    int leftend=…;
    之后,这样你就可以看到递归调用中的模式,也许可以确定不应该递归的地方,或者递归到过大的子范围的地方t无限递归,通常问题是您在输入到例程的同一子数组上递归调用了例程,或者您没有正确处理子数组长度为零的情况。为什么为4而不是
    ?4甚至不能保证为[left,right]…对于真实随机数,发生这种情况的概率(即使只有两种选择是可能的)是导致堆栈溢出所需的数千次。这种概率非常接近于零,更可能是宇宙射线在计算机内存中翻转了一点导致失败(是的,
    random
    只是一个伪随机生成器,但是它的分布非常均匀。它不会一直返回相同的数字)。问题是我没有处理子数组中只有两个元素的情况,不像你说的那样。