Home > Software design >  How to write partition for quicksort with C
How to write partition for quicksort with C

Time:02-15

I am writing an algorithm in C where the user types how many numbers they want to be sorted, then the program generates an array of random numbers, and sorts them. It also displays how much time it took to sort.

It only works for some of the trials, even if I use the same input. For example, if I ask the program to sort an array of 20 numbers, one of three things will happen:

  1. It will sort the array with no problems.
  2. The algorithm will time out and the terminal will print "Segmentation fault: 11".
  3. The algorithm will sort the numbers in the correct order, but one number will be replaced with a random negative number.

Here is my partition algorithm (the thing giving me trouble). I am choosing the first/left item as my pivot:

int partition(int arr[], int leftIndex, int rightIndex)
    {
        int i = leftIndex;
        int j = rightIndex;
        int pivotValue = arr[leftIndex];

        while(i < j){
            while(arr[i] <= pivotValue){
                i  ;
            }
            while(arr[j] > pivotValue && i < j){
                j--;
            }
            if(i < j){
                int temp = arr[i];
                arr[i] = arr[j];
                arr[j] = temp;
            }
        }

        int temp = arr[i - 1];
        arr[i - 1] = arr[leftIndex];
        arr[leftIndex] = temp;

        return i - 1;
    }

Here is my quicksort algorithm:

void quickSort(int arr[], int left, int right)
   {    
      if (left < right)
      {
        int pivot = partition(arr, left, right);

        quickSort(arr, left, pivot - 1);

        quickSort(arr, pivot   1, right);
      }
      return;
   }

Here is where I call everything in main():

int main()
  {
    clock_t sTime, eTime;

    int n;
    cout << "Enter an array size: " << endl;
    cin >> n; 
    cout << endl;
    int originalArray[n];
    
  
    cout << "Start generating random numbers..." << endl;
    for(int index=0; index<n; index  ){ 
        originalArray[index] = (rand()0) 1;

    }
    
    
    cout << "Original array values: "; 
    printArray(originalArray, n);
    cout<<"\n\n";
    

    //Makes a copy of the original array to preserve its original order
    int quickArray[sizeof(originalArray)];
    for(int i = 0; i < sizeof(originalArray); i  ){
        quickArray[i] = originalArray[i];
    }

    //Perform quicksort
    sTime = clock();
    quickSort(quickArray, 0, n-1);
    eTime = clock();
    printf("Sorted array by quickSort: ");
    printArray(quickArray, n);
    cout << "\nTotal CPU time used in quickSort: " << (double)(eTime-sTime) / CLOCKS_PER_SEC * 1000.0 << " ms" << endl;
    
    cout << endl; 

 
  
    return 0;
  }  

CodePudding user response:

I'm not sure if it's responsible for all the problems you're seeing, but I'd start with this bit of code:

        while(i < j){
            while(arr[i] <= pivotValue){
                i  ;
            }

What's this (especially the inner loop) going to do if the pivot is the largest value in the array?

CodePudding user response:


#include <bits/stdc  .h>

using namespace std;

int partition(int arr[], int leftIndex, int rightIndex)
    {
        int pivotIndex = leftIndex;
        int pivotValue = arr[pivotIndex];

        int i = leftIndex;
        int j = rightIndex;
        

        while(i < j){
            while(arr[i] <= pivotValue){
                i  ;
                if(i >= rightIndex) break;
            }
            while(arr[j] >= pivotValue){
                j--;
                if(j <= leftIndex) break;
            }
            if(i < j){
                int temp = arr[i];
                arr[i] = arr[j];
                arr[j] = temp;
            }
        }

        // swap
        arr[pivotIndex] = arr[j];
        arr[j] = pivotValue;

        return j;
    }
    void quickSort(int arr[], int left, int right)
   {    
   
      if (left < right)
      {
        int pivot = partition(arr, left, right);
        quickSort(arr, left, pivot - 1);
        quickSort(arr, pivot   1, right);
      }
      return;
   }

   int main()
  {
    clock_t sTime, eTime;

    int n;
    cout << "Enter an array size: " << endl;
    cin >> n; 
    cout << endl;
    int originalArray[n];
    
  
    cout << "Start generating random numbers..." << endl;
    for(int index=0; index<n; index  ){ 
        originalArray[index] = (rand()0) 1;

    }
    
    
    cout << "Original array values: "; 
    for(auto c: originalArray) {
        cout << c << " ";
    }

    cout<<"\n\n";
    

    //Makes a copy of the original array to preserve its original order
    int quickArray[n];
    for(int i = 0; i < n; i  ){
        quickArray[i] = originalArray[i];
    }

    //Perform quicksort
    sTime = clock();
    quickSort(quickArray, 0, n-1);
    eTime = clock();
    printf("Sorted array by quickSort: ");
    for(auto c: quickArray) {
        cout << c << " ";
    }
    cout << endl;
    cout << "\nTotal CPU time used in quickSort: " << (double)(eTime-sTime) / CLOCKS_PER_SEC * 1000.0 << " ms" << endl;
    
    cout << endl; 

 
  
    return 0;
  }  

There were several mistakes I've encountered. Firstly, I have added break statements in the while loops of partititon() method so that it breaks incrementing i or decrementing j if they exceeds the boundaries of the array. That was probably why you get segmentation fault sometimes.
Then I've changed the swapping part at the end of the partition and returned j. Probably this part was not erroneous, but I find this solution to be more readable.
Then I changed the part where you create the new array to int quickArray[n], you were creating the quickArray with sizeof(originalArray), which was wrong because it used to create an array with more elements. sizeof() returns (number of elements) * 4 since each int takes 4 bytes of memory.
Now, it should be working properly.

  • Related