0

I'm trying to sort this array by quick sort:

int[] arr = {25,23,21,29,28,22,24,27};

My quick sort function:

public static void quickSort(int[] arr) { // sorts array using quick sort algorithm
    if (arr[0] < arr[arr.length-1]) {
        int s = hoarePartitioning(arr);
        quickSort(Arrays.copyOfRange(arr, 0, s-1));
        quickSort(Arrays.copyOfRange(arr, s+1, arr.length));
    }
}

I used Hoare Partitioning:

public static int hoarePartitioning(int[] arr) {
    int pivot = arr[0];
    int i = 0;
    int j = arr.length;
    do {
        do {i++;} while(pivot >= arr[i] && i < arr.length);
        do {j--;} while(pivot <= arr[j] && j >= 0);
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }while(i <= j);

    int temp = arr[i];  //undo last swap when i >= j
    arr[i] = arr[j];
    arr[j] = temp;

    temp = arr[0];
    arr[0] = arr[j];
    arr[j] = temp;

    return j;
}

However, when I print out the array, this is the result:

22 23 21 24 25 28 29 27 

My Hoare Partitioning function works fine but I still don't understand why the array is not sorted. What am I doing wrong here? Thanks.

0

3 Answers 3

1

The quicksort method is fundamentally wrong:

    quickSort(Arrays.copyOfRange(arr, 0, s-1));
    quickSort(Arrays.copyOfRange(arr, s+1, arr.length));

Each time you recurse, you create a new arrays for the left and right subarrays, (try to) sort the new arrays, and then throw them away. Net result: the original array does not change.

Don't copy the subarrays. Pass the original array, along with the start and end of the subarray to be sorted in each recursive call. If necessary use an auxiliary function; e.g.

 public void quicksort(int[] array) {
     quicksort(array, 0, array.length - 1);
 }

 public void quicksort(int[] array, int start, int end) {
     ...
 }

There are some other problems too:

  1. The if test looks wrong. Why would you skip sorting the array / subarray in that condition? The actual test should be on the size of subarray that is being sorted ... not the subarray contents.

  2. The upper bounds calculations for the subarray look wrong; s - 1 is an inclusive bound, but arr.length is an exclusive bound. One of them must be wrong.

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

2 Comments

Thanks for the first suggestion. However, when I debug, both subarrays seem correct for my bounds.
I don't understand what you are saying. Which "first suggestion" are you referring to? The main problem or "other problem" #1?
0

Generic Hoare partition code as a single function. Using the middle value for pivot avoids worst case O(n^2) time complexity for already sorted or reverse sorted data. Any element except a[hi] can be used as the pivot with this specific code. There is no need to bounds check the indexes, because worst case, reaching the pivot will stop the initial inner loops, and any swap will allow the inner loops to be repeated without bounds check.

    public static void qsort(int[] a, int lo, int hi)
    {
        if(lo >= hi)
            return;
        int  p = a[lo+(hi-lo)/2];
        int  i = lo-1;
        int  j = hi+1;
        int t;
        while(true){
            while(a[++i] < p);
            while(a[--j] > p);
            if(i >= j)
                break;
            t     = a[i];
            a[i] = a[j];
            a[j] = t;
        }
        qsort(a, lo, j);
        qsort(a, j+1, hi);
    }

Comments

0

way this algorithm solution :

it's an in place recursive implementation of QuickSort encapsulated in this class.

this method quickSort(int low , int high) called recursivly to sort it's array .

Steps to implement Quick sort in place :

1- chose an element called pivot from array or list. generally is middle element pivot .

2- reorder the list , so that all element with the values is less than the pivot come before the pivot , and element with values is greater than the pivote come after the pivot . is also known as partitioning after partitioning .

3- recursively apply the above steps to the sub-list of elements with the smaller values and saperatly the sub-list , of elements with greater values.

4- if array its contain one element and zero element the array is sorted .

5- in this example we have array of integers is not sorted , and we need to sort array in ascending order.

6- our array is {6 , 5 , 3 , 1 , 8 , 4 , 2 , 7} and we first choose 3 as pivot .

7- now partitioning is starts and we pick 6 on left side of side because its greater than 3 , now in right side we leave 4 because its greater than 3 and pick 2 for swaping to 6 .

8- our array look like {2 , 5 , 3 , 1 , 8 , 7 , 6 , 4} .

9- now we pick 5 on left side because its greater than 3 and on right side pick 1 and swap with 5 .

10 - now our array look like is {2 , 1 , 3 , 5 , 8 , 7 , 6 , 4} and after we done with all elements respect to 3 as pivot .

11 - we can take sub-array at left side of 3 and applying swap 1 with 2

12- our array look like {1 , 2 , 3 , 5 , 8 , 7 , 6 , 4} this will sort the left sub-array .

13 - now we take the right side sub-array and we choose 4 as pivot and pick 5 because its greater than pivot and come after it , and swap them .

14- our array look like {1 , 2 , 3 , 4 , 8 , 7 , 6 , 5} and we choose 6 as pivot and choose 5 on right side 6 and pick 8 on right side 6 swap them , swap 5 against 8 .

15- now our array is {1 , 2 , 3 , 4 , 5 , 7 , 6 , 8 } and apply the same procedure.

16- finally our array sorted is {1 , 2 , 3 , 4 , 5 , 6 , 7 , 8}

    /**
     * java class to sort array of integers using QuickSort Algorithm     
     *   
     */

public class QuickSortDemo {

 public static void main(String args[]) {
   int unsorted[] = {6 , 5 , 3 , 1 , 8 ,7 , 2 , 4} ; 
     System.out.println("the original array : " + Arrays.toString(unsorted));

     // sort this array using quicksort algorithm.
     QuickSort algorithm = new QuickSort();
     algorithm.sort(unsorted);

 //printing the sorted array.
     System.out.println("the sorted array : " + Arrays.toString(unsorted));
  }



}

   
   /** java program to sort numbers using QickSort Algorithm , this 
     * quicksort is divide and conquer algorithm ,which divide the     
     * original list and merge it and sort it to created sorted output .   
     */

class QuickSort() {
   int input[];
   int length;
   
  public void sort(int [] numbers) {
    if(numbers == null || numbers.length == 0) {
        return;  
   }
     
    this.input= numbers;
    lenght = numbers.length;
    quickSort(0 , lenght - 1);

} 


//this method implements in-place QuickSort algorithm recursivly


   private void quickSort(int low , int high) {
      int i = low;
      int j = high;
      
     // this pivot it's in mid element.
      int pivot = input [low + (high - low) / 2];    
      
     //then we divide into tow arrays . 
         while(i <= j) {

   /** in above elaboration , in each iteration we will identify the 
    * numbers of left side which is greater than pivot ,
    * and then we identify the right number side which is less than pivot,
    */ once the search is complete we can swap both numbers.       

         while(input[i] < pivot) {
                 i++;        

         }  while(input[j] < pivot) {              
                j--;

           }

       
           if(i <= j) {
              swap(i , j);
               i++;
               j--;
            //move the index to next position to both sides.

            }

         }


        // call qickSort() method recursively
         if(i <= high) {
           quickSort (i , high);

          }

            if(low <= j) {
               quickSort(low , j);
             }

    }

   private void swap(int i , int j) {
     int temp = input[i];
     input[i] = input[j];       
     input[j] = temp;

     }



 }

Comments

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.