简体   繁体   中英

Quicksort for duplicates

I composed the following code for quick sort,and it seems to be doing fine for unique numbers.
However,it fails miserably when duplicates are present.
Help is appreciated in making the adjustment for duplicates:

class QuickSort{

    public static void sort(int left,int right,int[] data){
            if(right-left <= 0) return;
            int pivot=organize(left,right,data);
            sort(left,pivot-1,data);
            sort(pivot,right,data);
        }

        private static int organize(int left,int right,int[] data){
            int _right=right;
            int _left=left;
            int pivot=(left+right)%2==0?(left+right)/2:(left+right+1)/2;
            //Move the pivot to the extreme right.
            int pivotval=data[pivot];
            swap(pivot,right,data);
            left=left-1;//to adjust teh stating pointer
            while(true){

                while(right > 0 &&  data[--right]>pivotval);
                while(data[++left]<pivotval);
                if(right<=left) break;
                swap(left,right,data);

            }
            swap(left,_right,data);
            return left;
        }

        private static void swap(int left,int right,int[] data){
            int temp=data[right];
            data[right]=data[left];
            data[left]=temp;
        }

public static void main(String[] args){
                int N=Integer.parseInt(args[0]);
            int[] data=new int[N];
            Random r=new Random();
                    for(int i=0 ;i<N;i++)
                data[i]=r.nextInt(N);

                //After populating the array
                QuickSort.sort(0,data.length-1,data);

            }



            }

You should decide what you do with the equal elements. The simplest solution is to throw them on one side say to the right:

        while(true){

            while(right > 0 &&  data[--right]>=pivotval);
            while(data[++left]<pivotval);
            if(right<=left) break;
            swap(left,right,data);

        }

Problem here is that the algorithm will be really slow on some cases. Better approach is to form a third region of equal elements that grows in the center of the array from the pivot onwards.

A simpler and easier approach does two iterations - on first one you filter elements bigger than the pivot to form a group at the right end of the array, on second you form a group of smaller elements at the left end. Anything in between is equal to the pivot.

Hope this helps.

while(right > 0 && data[--right]>pivotval);

You need to reverse this test, otherwise you never get anywhere.

You move the pivot to the extreme right, but when you want to swap back the pivot after the while loop, you call swap(left,_right,data); , but left is not equal to pivot , pivot=(left+right)%2==0?(left+right)/2:(left+right+1)/2; , but left is uncertain. It looks like you want to use Hoare-Partition. Here it is:

private static int organize(int left,int right,int[] data){
        int pivot=(left+right)%2==0?(left+right)/2:(left+right+1)/2;
        //Move the pivot to the extreme right.
        int pivotval=data[pivot];
        //swap(pivot,right,data);
        left=left-1;//to adjust the stating pointer
        right = right + 1;
        while(true){

            while(right > 0 &&  data[--right]>pivotval);
            while(data[++left]<pivotval);
            if(right<=left) break;
            swap(left,right,data);

        }
        //swap(left,right,data);
        return left;
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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