2

For a homework assignment, I have to write an implementation of the QuickSort algorithm and use this to sort a list with 100k numbers in some random order.

In the first part of the assignment, I have to use the first item of the array as the pivot element. This indeed returns a sorted list. However, for the second part of the assignment I have to use the last item as the pivot, which results in a StackOverflowException. When I try it in a smaller collection of 8 records, it DOES work correctly. I've been looking at my code but I can't figure out where I'm making a mistake. Any help would be greatly appreciated. My code is as follows:

public class QuickSort {

    private QuickSortStrategyEnum quickSortStrategy;

    public QuickSort(QuickSortStrategyEnum quickSortStrategy) {

        this.quickSortStrategy = quickSortStrategy;
    }

    public List<Integer> sortIntegerArray(List<Integer> arrayList, int left, int right) {

        if ( left >= right ) {
            return arrayList;
        }

        int i = partition(arrayList, left, right);

        if (i <= right) {

            int pivotNew = partition(arrayList, i, right);
            int pivotIndex = arrayList.indexOf(pivotNew);

            arrayList = sortIntegerArray(arrayList, left , pivotIndex - 1);
            arrayList = sortIntegerArray(arrayList, pivotIndex + 1, right);
        }

        return arrayList;
    }

    private int partition(List<Integer> arrayList, int left, int right) {

        int pivot = getPivot(arrayList, left, right);
        int i = left + 1;

        for (int j = i; j <= right; j++) {

            if (arrayList.get(j) < pivot) {

                Collections.swap(arrayList, j, i);
                i++;
            }
        }

        Collections.swap(arrayList, left, i - 1);
        return i;
    }

    private int getPivot(List<Integer> arrayList, int left, int right) {

        int pivot = 0;

        switch (quickSortStrategy) {

            case FIRST:
            pivot = arrayList.get(left);
            break;

            case LAST:
            pivot = arrayList.get(right);
            break;
        }
        return pivot;
    }

}
1
  • It would help to know what method/line throws the exception. Commented Apr 15, 2012 at 18:59

3 Answers 3

5

Hint: What can happen if right == left + 1?

Sign up to request clarification or add additional context in comments.

2 Comments

+1 stepping through the code in a debugger would be useful. ;)
Beyond partition doing a bunch of busy-work, I don't see a problem with this condition. I'm only stepping through it in my head, though. :)
1

Along with the fact that David Harkness pointed out, there are problems with the partition logic. Try this out: (after removing things pointed by David Harkness)

private int partition(List<Integer> arrayList, int left, int right) {

    int pivot = getPivot(arrayList, left, right);
    int i = left - 1; 

    for (int j = left; j < right; j++) {
        if (arrayList.get(j) <= pivot) {
            i++;
            Collections.swap(arrayList, j, i);
        }
    }

    Collections.swap(arrayList, i+1, right);
    return i+1;
}

It will work for case when pivot is last element. Not for First element.

Read, understand the working on paper, dry run things out, write pseudo code and then say hello to Eclipse. Dont hurry to implement things.

3 Comments

If left is the first element (0), you make the index i -1, which causes Collections.swap(arrayList, j, i); to throw an IndexOutOfBoundsException. In Sander's code, the line is int i = left + 1;. Is this a copy-paste error?
Aaah you're right :) I dove into trying to program a solution too soon, before actually understanding the process. Now I understand how it works and can continue with this solution. I can't upvote you unfortunately as I haven't got enough points but thanks a lot!
@JessevanAssen Observe that before calling Collections.swap (arrayList, j, i), I incremented i. I have tested my code and it works
1

These two lines look fishy:

int pivotNew = partition(arrayList, i, right);
int pivotIndex = arrayList.indexOf(pivotNew);

Look at what partition returns and compare it to how you use its result.

1 Comment

Hmm you're right here, fixed this now. :) Unfortunately I haven't got enough points yet to upvote you..

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.