5

I read about quicksort algorithm and I don't understand how to choose pivot element. From tutorials I get example code of quciksort:

public void quicksort(int[] A, int left, int right) {
    int pivot = A[left + (right - left) / 2];
    int i = left;
    int j = right;
    while (i <= j) {
        while (A[i] < pivot) {
            i++;
        }
        while (A[j] > pivot) {
            j--;
        }
        if (i <= j) {
            exchange(i, j);
            i++;
            j--;
        }
    }

    if(left < j)
        quicksort(A,left,j);
    if(i < right)
        quicksort(A,i,right);
}

But why we choose pivot using this A[left + (right - left) / 2];?

Why not A[(right - left) / 2]

4
  • to pint middle index with base left Commented Jul 3, 2013 at 7:32
  • 2
    Why not? Because it would be incorrect. Run a few examples (either by hand or in the debugger) to see why. Commented Jul 3, 2013 at 7:32
  • @OliCharlesworth can you explain why it would be incorrect?
    – WelcomeTo
    Commented Jul 3, 2013 at 7:33
  • @MyTitle it can be incorrect read banarun's answer Commented Jul 3, 2013 at 7:42

6 Answers 6

11

Consider left=6, right=10, then (right-left)/2 is 2. You are choosing an element which is not in the range of your sub-array?

You can choose any element between 6 and 10 as for quick sort.But if you choose first or last element and if the array is sorted, then your algorithm may go to O(n^2) running time. So it is always better to choose middle element.

0
5

Suppose left=3 and right=9 then right-left/2 = 3 that is not middle but its 6 that is = left + (right - left) / 2. (just added base value left).

Thanks to @Dukeling:
You can simple write (left + right) / 2.

    left + (right-left)/2 
=>  2*left/2 + (right-left)/2    //multiply (left * 2/2)
=>  (2*left + right-left)/2 
=>  (left + right)/2
6
  • 3
    left + (right-left)/2 = 2*left/2 + (right-left)/2 = (2*left + right-left)/2 = (left + right)/2. Commented Jul 3, 2013 at 8:07
  • @Dukeling Wow!! interesting Thanks :), I would like to add in my answer. Commented Jul 3, 2013 at 8:10
  • 3
    @Dukeling (left+right)/2 is not same as left+ (right-left)/2 (if they are integer). left+right might cause integer overflow.
    – banarun
    Commented Jul 3, 2013 at 8:34
  • 1
    @banarun Yeah, I don't often sort arrays with more than 1 073 741 824 elements. Commented Jul 3, 2013 at 8:42
  • 2
    @Dukeling: You may be interested to know that this was a bug inside Java's binarySearch for many years: bugs.sun.com/bugdatabase/view_bug.do?bug_id=5045582. Commented Jul 3, 2013 at 15:24
1

may be you should understand this function means:quicksort the array A from index left to index right.And what is A[(right - left) / 2]?may be it is not an element of array A.

1

Left = minimum Right = maximum How do you get the middle? (Maximum - minimum) / 2

Basically it searches for the middle of the array as the pivot point.

Since the array does not start from 0, and the minimum is not a constant number, you add the minimum to the result - and that's the middle of the current array.

1
  • 1
    Yeah my bad, forgot to add the minimum. Middle is really (max - min)/2, but you add the minimum since the minimum is not 0 and may change. Thanks for notifying me of my mistake before someone could misunderstand.
    – Adam Cohen
    Commented Jul 3, 2013 at 7:42
1
( left + right ) / 2

may cause error due to overflow.

Suppose left = 1 & right = INT_MAX then ( left + right ) / 2 = 0, which is incorrect. This is caused due to overflow and to avoid this we choose left + (right - left) / 2. Mathematically both expressions are correct to choose the middle element.

0

Actually the selection of a pivot element is one of the most important parts of quicksort. An optimal selection usually depends on the structure of the arrays that you are receiving, and in general it is very hard to find a position for the pivot that suits every array.

In this particular example the tutorial is choosing as pivot the element in the middle of the segment being ordered, but probably there is no particular reason for doing so.

Me, I usually choose the last element of the segment pivot = A[right], only to avoid errors in arithmetics.

2
  • 1
    Always choosing the last element leads to terrible performance for an already-sorted array... Commented Jul 3, 2013 at 7:36
  • 1
    That's why I said that the selection depends on the structure of the received arrays...
    – cgledezma
    Commented Jul 3, 2013 at 9:05

Not the answer you're looking for? Browse other questions tagged or ask your own question.