Generic QuickSort causing StackOverflow?

  • Thread starter Enharmonics
  • Start date
  • Tags
    sorting
In summary, the code sorts an array by using the compareTo method. If left and right indices are out of order, the code does nothing. The quickSort algorithm is used to swap values while keeping i <= j.
  • #1
Enharmonics
29
2
I have to sort an array in increasing order based on the compareTo method. I'm not allowed to use the Arrays, Collections, Set, or Map classes.

Here's my code:

Java:
public static <T extends Comparable<? super T>>
    void sort (T[] arr)
    {
        // If arr is null, empty,
        // or only has 1 element,
        // it is already sorted
       
        if (arr == null || arr.length == 0
                || arr.length == 1)
            return;
       
        // Call overloaded sort method
       
        sort(arr, 0, arr.length - 1);
    }

    // OVERLOADED SORT METHOD
   
    public static <T extends Comparable<? super T>>
    void sort(T[] arr, int left, int right)
    {
       
        // To be used while sorting
       
        int i = left;
        int j = right;
       
        // Check if left and
        // right indices are out
        // of order. If they are,
        // nothing can be done
       
        if (right <= left)
            return;
       
        // Middle element used
        // as pivot
       
        T pivot = arr[(left + (right - left)) / 2];
       
        // temp will be used
        // to swap elements later
               
        T temp;
               
        // QuickSort algorithm
       
        while (i <= j)
        {
            // Look for values on
            // the left greater than
            // the pivot and values
            // on the right smaller
            // than the pivot
           
            // When you find both, swap them
           
            while (arr[i].compareTo(pivot) < 0)
            {
                i++;
            }
           
            while (arr[j].compareTo(pivot) > 0)
            {
                j--;
            }
           
            // Check that i hasn't
            // passed j already
           
            if (i <= j)
            {
               
                // Swap the items
               
                temp = arr[i];
                arr[i] = arr[j];
                arr[j] = temp;
               
                // Move both indices
                // to their next position
               
                i++;
                j--;
            }
        }
       
        // Recursive calls to the
        // sort method
       
        if (left < j)
            sort(arr, left, j);
        if (i < right)
            sort(arr, i, right);
    }

The trouble is, I'm getting a StackOverflow error at the line

Java:
while (arr[i].compareTo(pivot) < 0)

And then a whole bunch of them at the line

Java:
sort(arr, i, right);

The fact that I'm getting a bunch of repeated errors at the recursive call line tells me it might be an infinite recursion problem, but I just can't see why.

I also don't know why it's throwing an error at the compareTo line... based on how the method works, it seems like the logic is right? Don't know if it matters, but the array I'm using in my driver to test my QuickSort code is:

Java:
String[] wordArray = {"Droplet", "Blueberry", "Elephant",
                "Fate", "Apple", "Coconut", "Darjeeling"};

Any help with this would be appreciated. I'm kinda stumped.
 
Technology news on Phys.org
  • #2
You're performing a sort while you are sorting. The compareTo method calls the original sort and that one calls the overloaded version, which then calls itself.
 
  • Like
Likes jim mcnamara
  • #3
Borg said:
You're performing a sort while you are sorting. The compareTo method calls the original sort and that one calls the overloaded version, which then calls itself.

I'm a little confused, could you please explain this bit? I thought that (in this case, since the generic type is being replaced by String at compile time) the compareTo method just compared the lengths of the two Strings and returned the difference between them. I checked the Oracle documentation, which says

public int compareTo(String anotherString)

This is the definition of lexicographic ordering. If two strings are different, then either they have different characters at some index that is a valid index for both strings, or their lengths are different, or both. If they have different characters at one or more index positions, let k be the smallest such index; then the string whose character at position k has the smaller value, as determined by using the < operator, lexicographically precedes the other string. In this case, compareTo returns the difference of the two character values at position k in the two string -- that is, the value:

this.charAt(k)-anotherString.charAt(k)

Why is the sort method being called on the compareTo line? The only thing in the body of the while loop is a statement incrementing the value of i...
 
  • #4
Sorry, I misstated about the compareTo method. I thought that you were overloading the compareTo method.

It looks like it's getting into a state where it's comparing the same value over and over and not incrementing your values like you think.
 
  • #5
It's hard to tell for sure but it looks like your swap section might get into a state where it keeps flopping the middle value back and forth. In that case, one of the two recursive calls at the bottom will always be called so that it can never get out of the method. Also,based on the pivot declaration, it will only work for odd numbered arrays.
 
  • #6
The issue is the code to choose the pivot value, it should be:

Code:
        T pivot = arr[left + (right - left) / 2];

The current code is effectively using T pivot = arr[right / 2], and since right / 2 can be less than left, the pivot value is outside the range left to right. Consider the case where the chosen pivot value is less than all values in the range left to right, the index i will get incremented past right and perhaps past the end of the array, resulting in infinite recursion or segmentation fault.
 
  • Like
Likes Enharmonics
  • #7
rcgldr said:
The issue is the code to choose the pivot value, it should be:

Code:
        T pivot = arr[left + (right - left) / 2];

The current code is effectively using T pivot = arr[right / 2], and since right / 2 can be less than left, the pivot value is outside the range left to right. Consider the case where the chosen pivot value is less than all values in the range left to right, the index i will get incremented past right and perhaps past the end of the array, resulting in infinite recursion or segmentation fault.

Thank you SO much. That's exactly it.

For some reason I wrote

Code:
T pivot = arr[(left + (right - left)) / 2];

Which, as you said, is mathematically equivalent to arr[right / 2]. I have no idea why I added that extra set of parentheses. Good grief, I got to watch what I'm doing!
 

What is Generic QuickSort?

Generic QuickSort is a sorting algorithm that follows the divide and conquer approach to sort a given list of elements. It is a generic implementation of the QuickSort algorithm, which means it can sort any type of data as long as the data can be compared and ordered.

What is a StackOverflow?

A StackOverflow is an error that occurs when a program tries to use more memory than the call stack can hold. This usually happens when a recursive function calls itself too many times, causing the stack to overflow.

Why does Generic QuickSort cause a StackOverflow?

Generic QuickSort can cause a StackOverflow if the input list is too large or if there is a bug in the implementation that causes the recursive calls to never terminate. In some cases, the data being sorted may also be too complex, causing the algorithm to use up more memory than the call stack can handle.

How can I prevent StackOverflow when using Generic QuickSort?

To prevent StackOverflow when using Generic QuickSort, you can try increasing the size of the call stack, optimizing the implementation of the algorithm, or using an alternative sorting algorithm that is less likely to cause a StackOverflow. You can also ensure that the input data is not too large or complex.

Are there any alternative sorting algorithms that do not cause StackOverflow?

Yes, there are other sorting algorithms that are less likely to cause a StackOverflow, such as MergeSort, HeapSort, and Iterative QuickSort. These algorithms have different time and space complexities, so it is important to choose the one that best suits the data being sorted.

Similar threads

  • Programming and Computer Science
Replies
9
Views
1K
  • Programming and Computer Science
Replies
9
Views
2K
  • Programming and Computer Science
Replies
3
Views
1K
  • Programming and Computer Science
Replies
2
Views
2K
  • Engineering and Comp Sci Homework Help
Replies
18
Views
1K
  • Programming and Computer Science
Replies
4
Views
1K
  • Programming and Computer Science
Replies
2
Views
2K
  • Programming and Computer Science
Replies
3
Views
1K
  • Programming and Computer Science
Replies
17
Views
3K
  • Programming and Computer Science
Replies
3
Views
1K
Back
Top