How can a recursive call in a for loop be optimized? - c

I would like to know how a recursive function called in a loop of its own definition could be optimized like a tail call so as not to suffer from performance and stack size.
Typically, with pseudo code:
fun example(x):
if (something):
return // Stop the recursion
else:
for (/*...*/):
example() // Recursive call
For a concrete example, I would like to know how to apply such an optimization on the following program, found here:
// C program to print all permutations with duplicates allowed
#include <stdio.h>
#include <string.h>
/* Function to swap values at two pointers */
void swap(char *x, char *y)
{
char temp;
temp = *x;
*x = *y;
*y = temp;
}
/* Function to print permutations of string
This function takes three parameters:
1. String
2. Starting index of the string
3. Ending index of the string. */
void permute(char *a, int l, int r)
{
int i;
if (l == r)
printf("%s\n", a);
else
{
for (i = l; i <= r; i++)
{
swap((a+l), (a+i));
permute(a, l+1, r); // Recursive call to be optimized
swap((a+l), (a+i));
}
}
}
/* Driver program to test above functions */
int main()
{
char str[] = "ABC";
int n = strlen(str);
permute(str, 0, n-1);
return 0;
}
If the recursion becomes too deep, there is a risk of stack overflow. So how could we avoid that with this style of recursive functions (if possible, without drastically modifying the algorithm)?

This does not produce the exact same output, but is an iterative way of printing all permutations of a string. Adapted from cppreference.com.
void reverse(char *a, int l, int r)
{
while ((l != r) && (l != --r)) {
swap(a+(l++), a+r);
}
}
bool next_permutation(char *a, int l, int r)
{
if (l == r) return false;
int i = r;
if (l == --i) return false;
while (true) {
int i1 = i;
if (a[--i] < a[i1]) {
int i2 = r;
while (!(a[i] < a[--i2]))
;
swap(a+i, a+i2);
reverse(a, i1, r);
return true;
}
if (i == l) {
reverse(a, l, r);
return false;
}
}
}
void permute(char *a, int l, int r)
{
do {
printf("%s\n", a);
} while(next_permutation(a, l, r+1));
}
Demo

Related

[Solved by rewrite]Problem with passing pointer and recursive function

I'm really newbie to c programing, and I have no idea how can I make it work.
I want to make sort function that sorting array of integers by using 2 argument.
I want to use recursive on sort function. and sorting from end of array to first. by ascending order.
void ft_sorting(int *arr, int size);
but I don't know what went wrong. It totally out of my understanding with pointer and array. right now I really have no idea. Can some one pointing what I did wrong. And what I need to learn and fix. Thank you!
void ft_recure(int *a, int *b, int j, int k)
{
if (--j >= 0)
{
if (a[k] < b[j])
{
a[k] = b[j];
}
else
{
ft_recure(a[k], b[j], j, k);
}
}
else
return a[k];
}
void ft_sort(int *tab, int size)
{
int i;
int h;
while (size > 0)
{
i = size;
h = i;
tab[size] = ft_recure(tab, tab, i, h);
size--;
}
}
and also I try this.
int ft_recurs(int x, int y, int a, int b)
{
int j;
j = a;
if( a > 0)
{
if(*x < *(y - 1);)
{
b = *(y - 1);
*x = b;
}
ft_recurs(*x,*(y - 1),a - 1, b);
}
else
{
return *x;
}
}
void ft_sort_int_tab(int *tab, int size)
{
int memo;
int i;
while(--size >= 0)
{
i = size;
tab[size] = ft_recurs(tab[i], tab[size], i, memo);
}
}
In the first approach, you did improper when calling API again:
void ft_recure(int *a, int *b, int j, int k)
{
if (--j >= 0)
{
if (a[k] < b[j])
{
a[k] = b[j];
}
else
{
ft_recure(a[k], b[j], j, k);
}
}
else
return a[k];
}
a and b input to API ft_recure is a pointer but in ft_recure(a[k], b[j], j, k); it is value. You should correct this as: ft_recure(&a[k], &b[j], j, k); if you expect to input the address of k and j elements.
In your alternative usage:
int ft_recurs(int x, int y, int a, int b)
{
int j;
j = a;
if( a > 0)
{
if(*x < *(y - 1);)
{
b = *(y - 1);
*x = b;
}
ft_recurs(*x,*(y - 1),a - 1, b);
}
else
{
return *x;
}
}
The input is value but in the function you are using *x andn *(y-1) is not really a proper way. May be you could try int ft_recurs(int x[], int y[], int a, int b). But if so, you also need to provide pointer address at ft_recurs(*x,*(y - 1),a - 1, b); and then the issue come back to similar to first approach.

Selection sort algorithm using pointer arithmetic

I need to sort elements of array in ascending order using selection sort algorithm and pointer arithmetic.
That means the following (using pointer arithmetic):
find the minimum element in unsorted array;
swap the found minimum element with the first element
repeat it until the end of array
print sorted array
Code:
#include <stdio.h>
void swap(double **pp, double **qq) {
double *temp = *pp;
*pp = *qq;
*qq = temp;
}
void sortArray(double arr[], int n) {
double *q, *min;
q = min = arr;
while (min > arr + n) {
while (q < arr + n) {
if (*q < *min)
min = q;
q++;
}
min++;
swap(&min, &q);
}
}
void writeSorted(double arr[], int n) {
double *qq = arr;
while (qq < arr + n) {
printf("%g ", *qq);
qq++;
}
}
int main() {
double arr[4] = {2.1, 4.23, 3.67, 1.5};
int n = 4;
sortArray(arr, n);
writeSorted(arr, n);
return 0;
}
This code prints the same unsorted array. Do you know how to fix it?
There is an error about the role of swap: you have to swap the elements, not the corresponding pointers.
Moreover, there is a confusion about definition and role of each pointer.
In particular, it is important to keep trace of the pointer to the start of next iteration.
#include <stdio.h>
void swap(double *pp, double *qq) {
double temp = *pp;
*pp = *qq;
*qq = temp;
}
void sortArray(double arr[], size_t n) {
double *start = arr;
while (start < arr + n) {
double *q = start + 1;
double *min = start;
while (q < arr + n) {
if (*q < *min) min = q;
q++;
}
swap (start, min);
start++;
}
}
void writeArray(double arr[], size_t n) {
double *qq = arr;
while (qq < arr + n) {
printf("%g ", *qq);
qq++;
}
printf ("\n");
}
int main() {
double arr[] = {2.1, 4.23, 3.67, 1.5};
size_t n = sizeof(arr)/sizeof(*arr);
writeArray (arr, n);
sortArray(arr, n);
writeArray(arr, n);
return 0;
}
Besides, I don't know what are exactly your constraints for this exercise. Even by using pointers, some simplifications are possible. For example, for the print function:
void writeArray(double arr[], size_t n) {
while (n--) {
printf("%g ", *arr++);
}
printf ("\n");
}

Can anyone suggest me the necessary changes for my code?

A permutation, also called an “arrangement number” or “order,” is a rearrangement of the elements of an ordered list S into a one-to-one correspondence with S itself. A string of length n has n! permutation.
Below are the permutations of string ABC.
ABC ACB BAC BCA CBA CAB
The following code of all possible string permutation is coded using backtracking , but its not working , anyone please suggest necessary changes.
C program to print all permutations with duplicates allowed -
#include <stdio.h>
#include <string.h>
/* Function to swap values at two pointers */
void swap(char *x, char *y)
{
char temp;
temp = *x;
*x = *y;
*y = temp;
}
/* Function to print permutations of string
This function takes three parameters:
1. String
2. Starting index of the string
3. Ending index of the string. */
void permute(char *a, int l, int r)
{
int i;
if (l == r)
printf("%s\n", a);
else
{
for (i = l; i <= r; i++)
{
swap((a+l), (a+i));
permute(a, l+1, r);
swap((a+l), (a+i)); //backtrack
}
}
}
/* Driver program to test above functions */
int main()
{
char str[] = "ABC";
int n = strlen(str);
permute(str, 0, n);
return 0;
}
This is a classic case of OBOB (Of By One Bug).
The index of the last character of a n-length string is n-1, so when looping over all indices inside your string, the loop shouldn't be for (i = l; i <= r; i++), but for (i = l; i < r; i++).
Calling swap() with an index that is too big, creates weird effects, such as making your string shorter.
This is the permute() function after the change:
void permute(char *a, int l, int r)
{
int i;
if (l == r)
printf("%s\n", a);
else
{
for (i = l; i < r; i++) // corrected indices
{
swap((a+l), (a+i));
permute(a, l+1, r);
swap((a+l), (a+i)); //backtrack
}
}
}
It should work now.

Parallelization of Combination

I have got a piece of code that prints the combination of M number From N (nCm);
As it is a recursion, it works very slow when N is large.
#include <stdio.h>
#include <stdlib.h>
#define N 80
#define M 4
int result[M]= {0}; // THE ARRAY THAT SAVE THE RESULT OF ONE COMBINATION
int queue[N] = {0};
int top = 0;
void comb(int* input,int s, int n, int m)
{
if (s > n)
return ;
if (top == m)
{
for (int i = 0; i < m; i++)
{
result[i] = queue[i];
printf("%d\n", queue[i]);
}
}
queue[top++] = input[s];
comb(input,s+1, n, M);
top--;
comb(input,s+1, n, M);
}
int main()
{
int array[] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,
27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,
50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,
73,74,75,76,77,78,79,80};
printf("\ncombination():\n");
comb(array,0, N, M);
printf("\n");
}
I would like to know if there is any space for improvement in the algorithm above?
if possible, can I use openMP ?
Thanks
To me your code was even giving the desired output. see
I have changed
printing format each combination was not good enough.
repeated combinations. (note: else part of if statement added).
reduced 2 recursive call with a loop and a recursive call. (Less space.)
The required code is:
#include <stdio.h>
#include <stdlib.h>
#define N 20
#define M 6
int result[M]= {0}; // THE ARRAY THAT SAVE THE RESULT OF ONE COMBINATION
int queue[N] = {0};
int top = 0;
void comb(int* input,int s, int n, int m)
{
if (s > n)
return ;
if (top == m)
{
printf("\n");
for (int i = 0; i < m; i++)
{
result[i] = queue[i];
printf("%d ", queue[i]);
}
}else{
for(int ss=s;ss<n;ss++){
queue[top++] = input[ss];
comb(input,ss+1, n, m);
top--;
}
//comb(input,s+1, n, m);
}
}
int main()
{
int array[] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,
27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,
50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,
73,74,75,76,77,78,79,80};
printf("\ncombinations():\n");
comb(array,0, N, M);
printf("\n");
}

C - How to make function return a pointer?

This function should return a pointer to the first occurrence of the largest int in an array without using the index operator. It can find and print the largest int, but how do I make it return a pointer? And how do I test if it was successful?
int *arr_first_max(const int *a, size_t n) {
const int *k;
int largest = 0;
for (k = a; *k != '\0'; k++) {
if (*k > largest) {
largest = *k;
}
}
printf("%d\n", largest);
return &largest;
}
Edit: size_t n is supposed to be used but I'm not sure how to include it.
And another answer assuming:
n is length of array a (in terms of elements, not bytes)
You want to iterate through the whole array a
Then code is:
const int *arr_first_max(const int *a, size_t n) {
const int *largest = a;
while(n--) {
if(*a>*largest)
largest = a;
a++;
}
printf("%d\n", *largest);
return largest;
}
In all functions n is assumed to be >0.
Just keep your logic, but instead of storing the max, store the index to the max, in order to return a pointer to the array at that index.
int *arr_first_max(const int *a, size_t n) {
int i,l;
for (l=i=0 ; i<n ; i++)
if (a[i] > a[l]) l = i;
return a+l;
}
Edit Pointer only version (based on comments) which does n-1 iterations
const int *arr_first_max(const int *a, size_t n) {
const int *most;
for (most=a++ ; --n ; a++) if (*a > *most) most = a;
return most;
}
And since I misread the question, a recursive bonus!
const int *arr_first_max_r(const int *most, const int *a, size_t n) {
if (*a > *most) most = a;
return --n ? arr_first_max_r(most, ++a, n) : most;
}
to be called like this
printf("Biggest int is : %d\n", *arr_first_max_r(a, a, n));
This works. You detect the largest number like you did then run the same loop again to see where the number is then return that address. I also changed some data types from int to const int and I removed the 2nd parameter because you're checking for null characters.
#include <stdio.h>
#include <stdlib.h>
const int *arr_first_max(const int *a) {
const int *k;
int largest=0;
for (k = a; *k != '\0'; k++) {
if (*k > largest){
largest = *k;
}
}
for (k = a; *k != '\0'; k++) {
if (*k == largest){
return k;
}
}
}
int main(){
int nums[6]={7,2,1,5,4,6};
const int* y=arr_first_max(nums);
printf("%d\n", *y);
}
Assuming
the function's signature is correct and complete (arr_first_max alludes that you search in an array for the first max element)
and thus int* a is the pointer to the first element (i.e. equivalent to int a[] in a signature); I'll leave the const specifier in this case, though I think you could omit/discard it if the exercise permits that
size_t n is the size of the array or, in other words, the number of elements in the array
you want to return a pointer to largest element in the array without using the subscript [] operator
then this would be a solution
int *arr_first_max(const int *a, size_t n) {
int *largest, *k;
for (largest = k = a; (k - a) < n; k++)
if (*k > *largest)
largest = k;
return largest;
}
That is because I quote from The C Programming Language:
Pointer subtraction is also valid: if p and q point to elements of
the same array, and p<q, then q-p+1 is the number of elements from
p to q inclusive.
i won't guess what size_t n is for
int *arr_first_max( int *a, size_t n) {
int *largest = a;
while(*a){
a++;
if(*a>*largest) largest=a;
}
return largest;
}

Resources