Tail Call Elimination

We have discussed (in tail recursion) that a recursive function is tail recursive if recursive call is the last thing executed by the function.

filter_none

edit
close

play_arrow

link
brightness_4
code

// An example of tail recursive function
void print(int n)
{
    if (n < 0)  
       return;
    cout << " " << n;
  
    // The last executed statement is recursive call
    print(n-1);
}

chevron_right


We also discussed that a tail recursive is better than non-tail recursive as tail-recursion can be optimized by modern compilers. Modern compiler basically do tail call elimination to optimize the tail recursive code.

If we take a closer look at above function, we can remove the last call with goto. Below are examples of tail call elimination.



filter_none

edit
close

play_arrow

link
brightness_4
code

// Above code after tail call elimination
void print(int n)
{
start:
    if (n < 0) 
       return;
    cout << " " << n;
  
    // Update parameters of recursive call
    // and replace recursive call with goto
    n = n-1
    goto start;
}

chevron_right


QuickSort : One more example
QuickSort is also tail recursive (Note that MergeSort is not tail recursive, this is also one of the reason why QuickSort performs better)

filter_none

edit
close

play_arrow

link
brightness_4
code

/* Tail recursive function for QuickSort
 arr[] --> Array to be sorted,
  low  --> Starting index,
  high  --> Ending index */
void quickSort(int arr[], int low, int high)
{
    if (low < high)
    {
        /* pi is partitioning index, arr[p] is now
           at right place */
        int pi = partition(arr, low, high);
  
        // Separately sort elements before
        // partition and after partition
        quickSort(arr, low, pi - 1);
        quickSort(arr, pi + 1, high);
    }
}
// See below link for complete running code

chevron_right


The above function can be replaced by following after tail call elimination.

filter_none

edit
close

play_arrow

link
brightness_4
code

/* QuickSort after tail call elimination
  arr[] --> Array to be sorted,
  low  --> Starting index,
  high  --> Ending index */
void quickSort(int arr[], int low, int high)
{
start:
    if (low < high)
    {
        /* pi is partitioning index, arr[p] is now
           at right place */
        int pi = partition(arr, low, high);
  
        // Separately sort elements before
        // partition and after partition
        quickSort(arr, low, pi - 1);
  
        // Update parameters of recursive call
        // and replace recursive call with goto
        low = pi+1;
        high = high; 
        goto start;
    }
}
// See below link for complete running code

chevron_right


Therefore job for compilers is to identify tail recursion, add a label at the beginning and update parameter(s) at the end followed by adding last goto statement.

Next Article:
QuickSort Tail Call Optimization (Reducing worst case space to Log n )

This article is contributed by Dheeraj Jain. Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above

GeeksforGeeks has prepared a complete interview preparation course with premium videos, theory, practice problems, TA support and many more features. Please refer Placement 100 for details




My Personal Notes arrow_drop_up
Article Tags :
Practice Tags :


14


Please write to us at contribute@geeksforgeeks.org to report any issue with the above content.