简体   繁体   English

Java 快速排序算法 indexoutofbounds

[英]Java quickSort algorithm indexoutofbounds

I'm trying to implement a quickSort algorithm after learning about it.在了解它之后,我正在尝试实现一个快速排序算法。

package qsort;

public class QuickSort {
    
    public static void main(String[] args) {
        int arr[] = {10,16,8,12,15,6,3,9,5,100};
        quickSort(arr,0,(arr.length-1));
        for(int number:arr) {
            System.out.println(number);
        }
    }

    
    public static void quickSort(int[] arr, int l, int h) {
        if(l<h) {
            
            int j=partition(arr,l,h); //pivot position as j retrieved as the one sorted element
            int[] left = new int[j];
            int[] right = new int[(arr.length-j)];
            for(int index=0;index<j;index++) {
                left[index]=arr[index];
                }
            for(int index=j;index<arr.length;index++) {
                right[index-(j)]=arr[index];
            }
            
            quickSort(left,0,j);             //Sorts the first half of the array (i.e the elements before pivot
            quickSort(right,j+1,arr.length-1);            //SOrts the second half after pivot
        }
    }
    
    public static int partition(int[] arr, int l, int h) {
        
        if(arr[l]>arr[h]) {
            swap(arr[l],arr[h]);
        }
        
        
        int pivot = arr[l];
        int i=l;
        int j=h;     //i starts from the first and increments;  j starts from last and decrements
        while(i<j) {
            
            do {
                i++;
            }while(arr[i]<=pivot);          //i keeps incrementing until i points to a value greater than pivot
        
            do {
                j--;
            }while(arr[j]>pivot);               //j keeps decrementing until it finds a value less than pivot
        
            if(i<j) {
                swap(arr[i],arr[j]);
            }
        }
        swap(arr[l],arr[j]);            // swapping the first element l with the element in j so that the pivotal element can be ordered
        return j;                      //finally j points to the one sorted index where pivot should be placed
        
    }
    
    public static void swap(int a, int b){
        int temp=a;
        a=b;
        b=temp;
    }
}

And I've been clueless about IndexOutOfBoundsException and I'm not able to find out where or how it occurs.而且我对 IndexOutOfBoundsException 一无所知,我无法找出它发生的位置或方式。 Any help would be much appreciated.任何帮助将非常感激。

There are these issues:有这些问题:

  • swap doesn't swap. swap不交换。 It just swaps the values of two local variables, but has no knowledge about an array.它只是交换两个局部变量的值,但对数组一无所知。 When swap exits, those two local variables are discarded and nothing really changed.swap退出时,这两个局部变量被丢弃并且没有真正改变。 You need to pass the array reference to swap and the two indices that are involved, and then swap should change the values in that array at those two given indices.您需要将数组引用传递给swap和所涉及的两个索引,然后swap应该在这两个给定索引处更改该数组中的值。

  • left gets j values, but then a recursive call is made with h equal to j , which is an index that is out of range. left获取j值,但随后进行递归调用, h等于j ,这是一个超出范围的索引。 The left array has j elements, so its last index is j-1 , not j . left的数组有j个元素,所以它的最后一个索引是j-1 ,而不是j

  • right gets the remaining values, but then the recursive call is made with l equal to j+1 , but that has no relation to right , whose relevant values start at index 0, not at index j+1 . right获取剩余的值,但随后使用l等于j+1进行递归调用,但这与right无关,其相关值从索引 0 开始,而不是从索引j+1开始。

  • The whole idea to copy values into new arrays left and right is wrong.将值复制到新的 arrays left right整个想法是错误的。 This is not how quicksort is supposed to work.这不是快速排序应该如何工作的。 Even if left and right would be successfully sorted, this does not have any impact on arr , which remains unsorted.即使leftright可以成功排序,这对arr没有任何影响,它仍然未排序。 So you'd have done work for nothing.所以你会白白干活。 Quicksort is an inplace sorting algorithm, so you should always be working with arr , not with copies of partitions of it. Quicksort 是一种就地排序算法,因此您应该始终使用arr ,而不是使用它的分区副本。

Here is the correction of the relevant functions:以下是相关功能的更正:

    public static void quickSort(int[] arr, int l, int h) {
        if(l<h) {
            int j=partition(arr,l,h);
            // Don't create new arrays here, but sort the partition in-place:
            quickSort(arr,l,j-1);
            quickSort(arr,j+1,h);
        }
    }

    public static int partition(int[] arr, int l, int h) {
        if (arr[l]>arr[h]) {
            swap(arr, l, h); // swap needs the array reference, and two indices
        }
        int pivot = arr[l];
        int i=l;
        int j=h;
        while(i<j) {
            do {
                i++;
            }while(arr[i]<=pivot);
            do {
                j--;
            }while(arr[j]>pivot);
            if(i<j) {
                swap(arr, i, j); // see above
            }
        }
        swap(arr, l, j); // see above
        return j;
    }
    
    // swap needs the array reference and the indices to perform the swap in the array
    public static void swap(int[] arr, int i, int j){
        int temp=arr[i];
        arr[i]=arr[j];
        arr[j]=temp;
    }

I've been clueless about IndexOutOfBoundsException and I'm not able to find out where or how it occurs.我对 IndexOutOfBoundsException 一无所知,我无法找出它发生的位置或方式。

Debugging means you read the stack trace that includes this error message.调试意味着您阅读了包含此错误消息的堆栈跟踪。 It will give you the line number where it occurs (it was on the first line in partition ).它会给你它出现的行号(它在partition的第一行)。 Then when you have identified that line, you can start to really use a debugger, setting breakpoints and inspecting variables.然后,当您确定该行时,您可以开始真正使用调试器,设置断点并检查变量。 One of the first things you would notice, is that arr never changes: nothing gets moved in it.您会注意到的第一件事是arr永远不会改变:其中没有任何东西被移动。 And so you would continue to debug and resolve one thing after the other.因此,您将继续调试和解决一件又一件的事情。 It is what I did with your code.这就是我对你的代码所做的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM