Search code examples
csortingquicksort

Index problems with partition function in C


I was attempting to create a partition function for a quicksort that I want to run on an array of a Struct that I created. However, during runtime the indexes suddenly act weird and go crazy. (for example after a certain bigger=bigger-1 call, bigger suddenly gets the value 0 for no apparent reason.

This is my code:

int partition(Student studentsArray[], int left, int right)
{
    Student tempArr[right+1 - left];
    int smaller = left; int bigger = right;
    for(int i =left; i<right;i++)
    {
        if(stringComperator(studentsArray[i].name,studentsArray[right].name)>0)
        {
            tempArr[bigger]=studentsArray[i];
            bigger=bigger-1;
        }
        else
        {
            tempArr[smaller]=studentsArray[i];
            smaller=smaller+1;
        }
    }
    tempArr[smaller]=studentsArray[right];
    for(int i=left;i<right-left+1;i++)
    {
        studentsArray[i]=tempArr[i];
    }
    return smaller;
}

edit: updated code: seems to work inside of the method, but it seems like studentsArray won't change it values outside of the function call.

void swap(Student* a, Student* b)
{
    Student temp = *a;
    *a = *b;
    *b = temp;
}

int partition(Student studentsArray[], int left, int right)

{
    Student pivot = studentsArray[right];
    int i = left;
    for(int j = 0; j<right;j++)
    {
        if(stringComperator(studentsArray[j].name,pivot.name)<0)
        {
            swap(&studentsArray[i],&studentsArray[j]);
            i=i+1;
        }
    }
    swap(&studentsArray[i],&pivot);
    return i;
}

Solution

  • Your code has undefined behavior in lines such as:

      tempArr[bigger]=studentsArray[i];
    

    Your tempArr size is right+1 - left, and bigger starts as equals to right. This means that when left > 0, you are out of bounds.

    One of the many things that could happen in these cases, is overriding other automatic allocated variables, such as bigger.


    Few ways to solve it include pedantic checking for sizes. But, imho, the straightforward way is to avoid creating tempArr, and update the values inplace.