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

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.

Related

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

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

Passing pointer to an array as a parameter to a function

I tried to build a heap and finally print the elements in the form of an array.
Here it is the code (I know this doesn't really make sense but I just wanted to test my knowlwdge of heap and dynamic arrays):
#include <stdio.h>
#include <stdlib.h>
void heapiify(int *arr,int n, int i)
{
int largest=i;
int l=2*i+1; // left node
int r= 2*i+2; // right node
if(l<=n && *arr[l]>=*arr[i])
largest=l;
if (r <=n && *arr[r]<=*arr[i])
largest= r;
if(largest !=i)
{
int temp=*arr[i];
*arr[i]=*arr[largest];
*arr[largest]=temp;
}
heapify(*arr,n,largest);
}
void buildh(int *arr,int n,int r,int c)
{
int i;
for(i=n/2-1;i>=0;i--)
heapify(*arr,n,i);
output(*arr,r,c);
}
void output(int *arr,int r,int c)
{
int i,j;
for(i=0;i<r;i++)
{
for(j=0;j<c;j++)
{
printf("%d",*arr[i*c+j]);
}
printf("\n");
}
}
int main()
{
int i,j,r,c;
printf("enter the number of rows");
scanf("%d",&r);
printf("enter the number of columns");
scanf("%d",&c);
int n=r*c;
int *arr=malloc(n*sizeof(int));
for(i=0;i<r;i++)
{
for(j=0;j<c;j++)
scanf("%d",&arr[i*c+j]);
}
buildh(*arr,n,r,c);
}
I'm getting 9 errors which are all the same
invalid argument type of unary '*'( have int)
Your arr variable is of type pointer to int:
int *arr=malloc(n*sizeof(int));
So when you call buildh, which takes the same type, you have to pass it as-is:
buildh(arr,n,r,c);
Same for the other cases.
The problem is the dereference of arr, across your funtions in multiple places, and the passing of dereferenced *arr in your functions to int * parameters, you should pass arr, try:
//...
void heapify(int *arr, int n, int i)
{
int largest = i;
int l = 2 * i + 1; // left node
int r = 2 * i + 2; // right node
if (l <= n && arr[l] >= arr[i]) //here
largest = l;
if (r <= n && arr[r] <= arr[i]) //here
largest = r;
if (largest != i)
{
int temp = arr[i]; //here
arr[i] = arr[largest]; //here
arr[largest] = temp; //here
}
heapify(arr, n, largest); //here
}
void buildh(int *arr, int n, int r, int c)
{
int i;
for (i = n / 2 - 1; i >= 0; i--)
heapify(arr, n, i); //here
output(arr, r, c); //here
}
void output(int *arr, int r, int c)
{
int i, j;
for (i = 0; i < r; i++)
{
for (j = 0; j < c; j++)
{
printf("%d", arr[i * c + j]); //here
}
printf("\n");
}
}
int main()
{
//...
buildh(arr, n, r, c); //here
}

C++ 2 nested for loops transform to recursion

Hi i wanted to tranform this code into a recursive function:
int a3(int* a, int length) {
if(a == 0 || length <= 0) return 0;
int sum = 0;
for(int i = 0; i < length; i++) {
for(int j = i; j < length; j++) {
sum += a[j];
}
}
return sum;
}
My approach is :
int rec_help(int*a, int length);
int a3(int* a, int length) {
if(a == 0 || length <= 0) return 0;
else{
return rec_help(a,length) + rec_help(a+1,length-1) ;
}
}
int rec_help(int*a, int length){
if(a == 0 || length <= 0) return 0;
else{
int tmp = a[0];
return tmp + a3(a+1,length-1);
}
}
But i'm not getting it right.
With a3() i wanted to simulate the first for loop, and i think there is my problem :D
And with rec_help() the second loop and the body, but im mixing things here.
I would appreciate any kind of help :)
Because you have 2 loop, if you want your function to be recursive, you will need 2 recursive functions, one which will do the job of the first loop and a second to do the job of your second loop...
Something like that should work :
int a3_rec(int *a, int length)
{
if (length == 0)
return (0);
return (*a + a3_rec(a + 1, length - 1));
}
int a3_rec_hat(int *a, int length)
{
if (a == 0 || length == 0)
return (0);
return (a3_rec(a, length) + a3_rec_hat(a + 1, length - 1));
}
I hope I've helped you :)
As a general rule, when you transform loops into recursion, every loop becomes a function and any non-local variables it uses become arguments.
Your original code is
int a3(int* a, int length) {
if(a == 0 || length <= 0) return 0;
int sum = 0;
for(int i = 0; i < length; i++) {
for(int j = i; j < length; j++) {
sum += a[j];
}
}
return sum;
}
Let's start with the innermost loop. It uses j, i, length, sum, and a from the surrounding scope.
void a3_loop0(int *pj, int length, int *psum, int *a) {
if (*pj < length) {
*psum += a[*pjj];
(*pj)++;
a3_loop0(pj, length, psum, a);
}
}
int a3(int* a, int length) {
if(a == 0 || length <= 0) return 0;
int sum = 0;
for(int i = 0; i < length; i++) {
int j = i;
a3_loop0(&j, length, &sum, a);
}
return sum;
}
This is a very literal and mechanical translation. Every mutable variable has become a pointer (in C++ you'd use references for this), which leads to somewhat ugly and non-functional code (well, code that doesn't use idiomatic functional style). But it works, and we can proceed to the next loop in the same way:
void a3_loop0(int *pj, int length, int *psum, int *a) {
if (*pj < length) {
*psum += a[*pj];
(*pj)++;
a3_loop0(pj, length, psum, a);
}
}
void a3_loop1(int *pi, int length, int *psum, int *a) {
if (*pi < length) {
int j = *pi;
a3_loop0(&j, length, psum, a);
(*pi)++;
a3_loop1(pi, length, psum, a);
}
}
int a3(int* a, int length) {
if(a == 0 || length <= 0) return 0;
int sum = 0;
int i = 0;
a3_loop1(&i, length, &sum, a);
return sum;
}
Technically we're done now, but there's a number of things we can clean up.
The first thing I'd do is to change the type of a to const int * because a3 never modifies any of its elements.
The second thing I'd do is to hoist the loop variables *pi / *pj into their functions; they don't really need to be pointers to mutable objects elsewhere.
void a3_loop0(int j, int length, int *psum, const int *a) {
if (j < length) {
*psum += a[j];
a3_loop0(j + 1, length, psum, a);
}
}
void a3_loop1(int i, int length, int *psum, const int *a) {
if (i < length) {
a3_loop0(i, length, psum, a);
a3_loop1(i + 1, length, psum, a);
}
}
int a3(const int *a, int length) {
if (a == 0 || length <= 0) return 0;
int sum = 0;
a3_loop1(0, length, &sum, a);
return sum;
}
This already simplifies and shortens the code a bit.
The next step is to actually return something from these helper functions. Currently they use *psum as an accumulator and return void. We can keep the use of an accumulator but return the result directly (instead of through an output parameter) as follows:
void a3_loop0(int j, int length, int sum, const int *a) {
if (j < length) {
return a3_loop0(j + 1, length, sum + a[j], a);
}
return sum; // this was implicit before; "return sum unchanged"
}
void a3_loop1(int i, int length, int sum, const int *a) {
if (i < length) {
return a3_loop1(i + 1, length, a3_loop0(i, length, sum, a), a);
}
return sum; // ditto
}
int a3(const int *a, int length) {
if (a == 0 || length <= 0) return 0;
return a3_loop1(0, length, 0, a);
}
This version of the code is "purely functional" in that it never modifies any variables; it only passes and returns values to and from functions, respectively.
If we wanted to, we could get rid of all if statements and write everything as expressions:
void a3_loop0(int j, int length, int sum, const int *a) {
return j < length
? a3_loop0(j + 1, length, sum + a[j], a)
: sum;
}
void a3_loop1(int i, int length, int sum, const int *a) {
return i < length
? a3_loop1(i + 1, length, a3_loop0(i, length, sum, a), a)
: sum;
}
int a3(const int *a, int length) {
return a == 0 || length <= 0
? 0
: a3_loop1(0, length, 0, a);
}
I'll post this because I see the other answers use 1 function per loop which isn't necessary.
You can have just 1 recursive function:
int a3_impl(int* a, int length, int i, int j)
{
if (i >= length)
return 0;
if (j >= length)
return a3_impl(a, length, i + 1, i + 1);
return a[j] + a3_impl(a, length, i, j + 1);
}
int a3(int* a, int length)
{
if(a == 0 || length <= 0)
return 0;
return a3_impl(a, length, 0, 0);
}

Quick Sort Array Random Number Generator Nothing Printed Error

I have this C code that creates an array with 100 random numbers and I want to sort it using quick sort, but it always gives a Segmentation fault error.
Here is the code:
#define MAX 100
int a[MAX];
void quick_sort(double *x, int l, int r) {
int l1, r1;
if (l < r) {
l1 = l;
r1 = r;
do {
while (l1 < r && x[l1 - 1] <= x[l - 1]) {
l1++;
}
while (l < r1 && x[r1 - 1] >= x[l - 1]) {
r1--;
}
if (l1 < r1) {
swap(&x[l1 - l], &x[r1 - 1]);
}
} while (l1 < r1);
swap(&x[l - 1], &x[r1 - 1]);
quick_sort(x, l, r1 - 1);
quick_sort(x, r1 + 1, r);
}
}
void printArray(int a[], int size) {
int i;
for (i = 0; i < size; i++)
printf("%d ", a[i]);
printf("\n");
}
int main() {
int i = 1;
int a_size = sizeof(a) / sizeof(a[0]);
srand((unsigned int)time(NULL));
for (i = 0; i < MAX; i++) {
a[i] = rand() % 501;
}
quick_sort(a, 0, a_size);
printArray(a, a_size);
}
The error is that nothing prints when I run the program.
Can someone help me with the problem?
There are many problems in your code:
You do not include <stdio.h>, <stdlib.h>, nor <time.h>.
Your quick_sort function expects a pointer to an array of double, yet you pass an array of int.
The code for function swap() is not posted.
Your implementation of the Quick Sort algorithm in function quick_sort is flawed:
you should not scan slices of size 1, use (r - l > 1).
You cannot use x[l - 1] as pivot, it is not even part of the slice to be sorted. Furthermore, you should extract the pivot from the array before the swapping phase as it may move.
You should not name a variable l, it looks too close to 1 and you do make the mistake here: swap(&x[l1 - l], &x[r1 - 1]);
You should initialize l1 and r1 such that you do not need to subtract 1 in so many places, it leads to confusion and erroneous code.
Study the algorithms from the Wikipedia article and translate one to C.
Here is a corrected version:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define MAX 100
void swap(int *a, int *b) {
int x = *a;
*a = *b;
*b = x;
}
// Quick Sort using Hoare's original partition scheme
void quick_sort(int *x, int l, int r) {
if (l < r) {
int pivot = x[l];
int l1 = l - 1;
int r1 = r;
for (;;) {
while (x[++l1] < pivot)
continue;
while (x[--r1] > pivot)
continue;
if (l1 < r1) {
swap(&x[l1], &x[r1]);
} else {
break;
}
}
quick_sort(x, l, r1 + 1);
quick_sort(x, r1 + 1, r);
}
}
void printArray(int a[], int size) {
for (int i = 0; i < size; i++) {
printf("%d ", a[i]);
}
printf("\n");
}
int main(void) {
int a[MAX];
int a_size = sizeof(a) / sizeof(a[0]);
srand((unsigned int)time(NULL));
for (int i = 0; i < MAX; i++) {
a[i] = rand() % 501;
}
quick_sort(a, 0, a_size);
printArray(a, a_size);
return 0;
}

QuickSort Algorithm Number of Comparisons

I have been taking a class at Coursera and we had an assignment which was to count the number of comparisons QuickSort does on a 10,000 size array a numbers.
#include <stdio.h>
#define SIZE 10000
int ComparsionCount = 0;
void swap(int a[], int i, int j) {
int temp = a[j];
a[j] = a[i];
a[i] = temp;
}
int partition(int a[], int l, int r){
int p = a[l];
int i = l + 1;
int j;
for (j = l + 1; j <= r; j++) {
if (a[j] < p) {
swap(a, j, i);
i++;
}
}
swap(a, l, i - 1);
return (i - 1);
}
void add(int i) {
ComparsionCount += i;
}
int QuickSort(int a[], int l, int r){
int pivot;
if (r > 1) {
add(r - 1);
pivot = partition(a, l, r);
QuickSort(a, l, pivot - 1);
QuickSort(a, pivot + 1, r);
}
return pivot;
}
int main() {
FILE *fr;
int arr[SIZE];
int i = 0;
int elapsed_seconds;
char line[80];
fr = fopen("QuickSort.txt", "r");
while (fgets(line, 80, fr) != NULL)
{
/* get a line, up to 80 chars from fr. done if NULL */
sscanf (line, "%ld", &elapsed_seconds);
/* convert the string to a int */
arr[i] = atoi(line);
i++;
}
fclose(fr); /* close the file prior to exiting the routine */
printf("%d\n",QuickSort(arr,0,SIZE-1));
}
I am getting an segmentation error. I have identified that the problem lies in two recursive calls of QuickSort.
I have no idea of how to solve this problem,your help would be appreciated a lot
Thanks in advance.
I think you should add the code in the partition function like this:
for (j = l + 1; j <= r; j++) {
count++;
if (a[j] < p) {
...
}
Note: count is a global variable initialized to 0.

Resources