Maximum recursion depth exceeded. Stack overflow exception

0

I am currently writing an algorithm to analyze the sorting algorithms. I have many inputs from 1000 numbers up to 1 000 000 inputs. Currently I'm having some problems with the Quick Sort function. As I have an input of 1 000 000 of similar numbers (numbers between 1-10) this code will throw me an error (0xC00000FD) (seems to be an stack overflow exception). Now, I don't know what to do to lower the numbers of recursion calls or how to increase the stack so there could be multiple recursion calls. I'm attaching the code for the Quick Sort.

void swap(int *xp, int *yp)
    {
        int temp = *xp;
        *xp = *yp;
        *yp = temp;
    }

int partition (int arr[], int low, int high)
{
    int pivot = arr[(low+high)/2];
    int i = (low - 1);

    for (int j = low; j <= high - 1; j++)
    {
        if (arr[j] < pivot)
        {
            i++;
            swap(&arr[i], &arr[j]);
        }
    }
    swap(&arr[i + 1], &arr[high]);
    return (i + 1);
}
void quicksort(int A[], int l, int h)
{
    if (l < h) {
        int p = partition(A, l, h);
        quicksort(A, l, p - 1);
        quicksort(A, p + 1, h);
    }
}
c
recursion
bigdata
stack-overflow
quicksort

2 Answers

2

If you get stack overflows during recursion, it means that your recursion is broken. Recursion in general should be avoided since it has a huge potential for creating slow and dangerous algorithms. If you are a beginner programmer, then I would strongly advise to simply forget that you ever heard about recursion and stop reading here.

The only time it can be reasonably allowed is when the recursive call is placed at the end of the function, so-called "tail call recursion". This is pretty much the only form of recursion that the compiler can actually optimize and replace with an inlined loop.

If it cannot perform tail-call optimization, then it means that a function is actually called each time you do recursion. Meaning that the stack keeps piling up and you also get function call overhead. This is both needlessly slow and unacceptably dangerous. All recursive functions you ever write must therefore be disassembled for the target, to see that the code has not gone haywire.

Since this code seems to be taken from this site https://www.geeksforgeeks.org/iterative-quick-sort/, they already described most of these problems with the code for you there. They have a "quickSortIterative" function at the bottom which is a much better implementation.

My take is that the aim of the tutorial is to show you some broken code (the code in your question) then demonstrate how to write it correctly, by getting rid of the recursion.

answered on Stack Overflow Mar 8, 2021 by Lundin
0

Stack overflow can be avoided by only recursing on the smaller partition:

void quicksort(int A[], int l, int h)
{
    while (l < h) {
        int p = partition(A, l, h);
        if((p - l) <= (h - p)){
            quicksort(A, l, p - 1);
            l = p + 1;
        } else {
            quicksort(A, p + 1, h);
            h = p - 1;
        }
    }
}

However, worst case time complexity remains at O(n^2), and the Lomuto partition scheme used in the questions code has issues with a large number of duplicate values. Hoare partition scheme doesn't have this issue (in fact more duplicates results in less time).

https://en.wikipedia.org/wiki/Quicksort#Hoare_partition_scheme

Example code with partition logic in quicksort:

void quicksort(int a[], int lo, int hi)
{
    int p;
    int i, j;
    while (lo < hi){
        p = a[lo + (hi - lo) / 2];
        i = lo - 1;
        j = hi + 1;
        while (1){
            while (a[++i] < p);
            while (a[--j] > p);
            if (i >= j)
                break;
            swap(a+i, a+j);
        }
        if(j - lo < hi - j){
            quicksort(a, lo, j);
            lo = j+1;
        } else {
            quicksort(a, j+1, hi);
            hi = j;
        }
    }
}
answered on Stack Overflow Mar 8, 2021 by rcgldr

User contributions licensed under CC BY-SA 3.0