Bubble sort using recursive function in C - c

When I call my bubble sort recursive function, the array is not getting sorted.
#include"stdio.h"
void bubble(int *arr,int n,int vidx){
if(n==0)
return;
if(vidx == n)
bubble(arr,n-1,0);
return;
if(*(arr+vidx) > *(arr+vidx+1)){
int temp = *(arr+vidx);
*(arr+vidx) = *(arr+vidx+1);
*(arr+vidx+1) = temp;
bubble(arr,n,vidx+1);
return;
}
} int main(){
int a[] = {5,4,3,2,1};
bubble(&a,5,0);
for(int i = 0 ; i < 5 ; i++)
printf("%d,",a[i]);
return 0; }
Actual Output : 5,4,3,2,1,
Expected Output : 1,2,3,4,5,

if(vidx == n)
bubble(arr,n-1,0);
return;
This is why I advocate always using braces. As-is, that code is equivalent to:
if(vidx == n){ bubble(arr,n-1,0); }
return;
Most of the body of the bubble function is unreachable.
Edit: Incidentally, I notice two other bugs in what's left:
vidx can go up to the length of the array, so vidx+1 will index past the end, which could cause problems
When you hit two adjacent elements that are in the right order with respect to each other (i.e. *(arr+vidx) <= *(arr+vidx+1)), you make it to the end of the function without recursing further, stopping the sort prematurely.

Related

A function in C runs for a set of values but gives Segmentation Fault: 11 for another

I am trying to find unique non-zero intersection between two sets. I have written a program which works for some set of arrays but gives segmentation fault for some. I have been trying to figure out why but have failed, any help will be greatly valued. The thing is the functions defined (NoRep and ComEle) are working fine but are unable to return the value to the assigned pointer in the case when Seg Fault is shown. Below is the code:
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<string.h>
int* ComEle(int ar_1[], int size_ar1, int ar_2[], int size_ar2);
int* NoRep(int a[], int l1);
int main ()
{
// Case 1: Gives segmentation fault
int A[10] = {1,1,0,2,2,0,1,1,1,0};
int B[10] = {1,1,1,1,0,1,1,0,4,0};
int *C = ComEle(A,10,B,10); printf("check complete\n");
// //Case 2: Does not give segmentation fault
// int A[4] = {2,3,4,5};
// int B[4] = {1,2,3,4};
// int *C = ComEle(A,4,B,4); printf("check complete\n");
}
//---------------- Local Functions --------------------//
int* ComEle(int ar_1[], int size_ar1, int ar_2[], int size_ar2) {
// sort of intersection of two arrays but only for nonzero elements.
int i=0, j=0, cnt1 = 0;
int temp1 = size_ar1+size_ar2;
int CE1[temp1]; for(i=0;i<temp1;i++) {CE1[i] = 0;}
/* Size of CE1 is knowingly made big enough to accommodate repeating
common elements which can expand the size of resultant array to
values bigger than those for the individual arrays themselves! */
for(i=0;i<size_ar1;i++) {
j = 0;
while(j<size_ar2) {
if(ar_1[i]==ar_2[j] && ar_1[i]!=0) {
CE1[cnt1] = ar_1[i];
cnt1++;
}
j++;
}
}
// Have to remove repeating elements.
int *CE = NoRep(CE1, cnt1);
for(i=0;i<(CE[0]+1);i++) {printf("CE:\t%d\n", CE[i]);}
printf("ComEle: %p\n",CE);
return(CE);
}
int* NoRep(int a[], int l1) {
int cnt = 0, i = 0, j =0;
int *NR; NR = (int*)calloc((l1), sizeof(int));
//int NR[l1]; for(i=0;i<l1;i++) {NR[i] = 0;}
for(i=0;i<l1;i++) {
j = 0;
while(j<i) {
if(a[i]==a[j]) {break;}
j++;
}
if(j == i) {
cnt++;
NR[cnt] = a[i];
}
}
NR[0] = cnt; // First element: # of relevant elements.
printf("NoRep: %p\n",NR);
return(NR);
}
Thanks again for your help!
Take a look at this code:
int temp1 = size_ar1+size_ar2;
int CE1[temp1]; for(i=0;i<temp1;i++) {CE1[i] = 0;}
/* Size of CE1 is knowingly made big enough to accommodate repeating
common elements which can expand the size of resultant array to
values bigger than those for the individual arrays themselves! */
for(i=0;i<size_ar1;i++) {
j = 0;
while(j<size_ar2) {
if(ar_1[i]==ar_2[j] && ar_1[i]!=0) {
CE1[cnt1] = ar_1[i];
cnt1++;
}
j++;
}
}
Here you have nested loops, i.e. a for-loop with a while-loop inside. So - in worst case - how many times can cnt1 be incremented?
The answer is size_ar1 * size_ar2
But your code only reserve size_ar1 + size_ar2 element for CE1. So you may end up writing outside the array.
You can see this very easy by printing cnt1 inside the loop.
In other words - your CE1 is too small. It should be:
int temp1 = size_ar1*size_ar2; // NOTICE: * instead of +
int CE1[temp1]; for(i=0;i<temp1;i++) {CE1[i] = 0;}
But be careful here - if the input arrays are big, the VLA gets huge and you may run in to stack overflow. Consider dynamic memory allocation instead of an array.
Besides the accepted answer: I have been missing a break statement in the while loop in ComEle function. It was not giving me the expected value of cnt1. The following will be the correct way to do it:
for(i=0;i<size_ar1;i++) {
j = 0;
while(j<size_ar2) {
if(ar_1[i]==ar_2[j] && ar_1[i]!=0) {
CE1[cnt1] = ar_1[i];
cnt1++;
break;
}
j++;
}
}
This will also do away with the requirement for a bigger array or dynamic allocation as suggested (and rightly so) by #4386427

Parameter not being passed correctly.

I have a Piece of code here. The code Runs fine and there is no error shown by the system. Although I have a recursive function the recursion does not occurs.
Here is my code....
What exactly is the problem???
int no_of_moves(int n,int s[], int m)
{ int move=0,i;
if(n==1)
return 0;
for(i=m-1;(i>=0&&s[i]!=n&&n%s[i]==0); i--)
{
//printf("(%d %d)",n,s[i]);
move = max(move, 1+no_of_moves(s[i],s,m));
}
return move;
}
There is nothing easier than add debug output like this
int no_of_moves(int n,int s[], int m)
{ int move=0,i;
printf("Recursion test\n");
if(n==1)
return 0;
for(i=m-1;( i>=0 && s[i] != n && n%s[i] == 0); i--)
{
printf("(%d %d)",n,s[i]);
move = max(move, 1+no_of_moves(s[i],s,m));
}
return move;
}
Note
printf("Recursion test\n");
Output
Recursion test
(12 4)Recursion test
(12 3)Recursion test
(12 2)Recursion test
It means that your function is called recursively 3 times.
The problem why does the function give you wrong output is in passing parameters. But Q was
Program not entering into Recursion
but it does.

Can't return the correct int in C

i'm using this function (quicksort algorithm) and im
trying to get the total relocations also. In order to collect as much statitics i can i have to execute the function many times using a for loop, so after the end of the algorithm i must make the static variable equal to zero after copying it to a non-static variable and return it. Instead i always get a 0 return.
Please help me to not get a 0 grade too :P Thanks
int quicksort(int left, int right, int *p)
{
static int staticrelocations=0;
int i,j,mid,x,temp,relocations;
if(left<right)
{
i=left;
j=right;
mid=(left+right)/2;
x=p[mid];
while(i<j)
{
while(p[i]<x)
i++;
while(p[j]>x)
j--;
if(i<j)
{
if(p[i]==p[j])
{
if(i<mid)
i++;
if(j>mid)
j--;
}
else
{
temp=p[i];
p[i]=p[j];
p[j]=temp;
staticrelocations++;
}
}
}
quicksort(left,j-1,p);
quicksort(j+1,right,p);
}
relocations=staticrelocations;
staticrelocations=0;
return relocations;
}
You recurse into quicksort(), and in the innermost invocation you set staticrelocations = 0 before returning its former value. However, in the outer quicksort(), you ignore the return value of the inner quicksort. The outer quicksort returns the zeroed staticrelocations. Instead, you should go like this:
int quicksort()
{
int relocs = 0;
/* function logic */
if (/*did a new relocation*/)
relocs++;
relocs += quicksort(); //inner quicksort recursively
return relocs;
}

Segmentation fault (core dumped) error, in a C search function

I'm trying to write a C program to take an array of discrete positive integers and find the length of the longest increasing subsequence.
'int* a' is the array of randomly generated integers, which is of length 'int b'
call:
lis_n = answer(seq, seq_size);
function:
int answer(int* a, int b) {
if (a == NULL) {return -1;}
int i = 0;
int j = 0;
int k = 0;
//instantiate max and set it to 0
int max = 0;
//make an array storing all included numbers
int included[b];
memset(included, 0, b*sizeof(int));
//create a pointer to the index in included[] with the largest value
int indexMax = 0;
//create a pointer to the index in a[]
int indexArray = 0;
//index of a[] for max included
int maxToA = 0;
//set the first included number to the first element in a[]
included[indexMax] = a[indexArray];
//loop until break
while (1) {
if (a[indexArray] > included[indexMax]/*digit greater than last included*/) {
//include the digit
included[indexMax+1] = a[indexArray];
//increment current max pointer
indexMax++;
}
j = b - 1;
while (indexArray >= j/*pointer is at end"*/) {
if (j == (b - 1)) {
if ((indexMax+1) > max/*total is greater than current max*/) {
max = indexMax + 1;
}
}
if (a[b-1] == included[0]/*last element is in included[0], stop*/) {
return max;
} else {
//max included is set to zero
included[indexMax] = 0;
//max included pointer decreased
indexMax--;
//set array pointer to new max included
for (k=0;k<(b-1);k++) {
if (a[k] == included[indexMax]) {
indexArray = k;
}
}
//increment array pointer
indexArray++;
j--;
}
}
indexArray++;
printf("(");
for (i=0;i<b;i++) {
printf("%d,",included[i]);
}
printf(")");
}
}
I'm receiving 'Segmentation fault (core dumped)' in the terminal upon running.
Any help would be awesome.
You have declared
int indexMax = 0;
And here you use it as an array index
incuded[indexMax] = 0;
You increment and decrement it
indexMax++;
...
indexMax--;
You check its range but you don't limit it, you alter the value you compare it with
if ((indexMax+1) > max/*total is greater than current max*/) {
max = indexMax + 1;
}
You never check indexMax against b or with 0
int included[b];
So you are almost guaranteed to exceed the bounds of included[].
Some general points of advice. Make your function and variable names meaningful. Avoid making a premature exit from a function wherever possible. Avoid while(1) wherever possible. And never make assumptions about array sizes (including C "strings"). It might seem hard work putting in the overhead, but there is a payoff. The payoff is not just about catching unexpected errors, it makes you think about the code you are writing as you do it.
I've done something like this for homework before. I got help from:
https://codereview.stackexchange.com/questions/30491/maximum-subarray-problem-iterative-on-algorithm
Make sure you are not trying to index past the size of your array. What I would do would be to find out the size of array a[] (which looks like it is b) and subtract 1. Make sure you are not trying to access past the size of the array.

Write the definition of a function, isReverse

Write the definition of a function, isReverse , whose first two parameters are arrays of integers of equal size, and whose third parameter is an integer indicating the size of each array. The function returns true if and only if one array is the reverse of the other. ("Reverse" here means same elements but in reverse order.)
int isReverse(int array1[], int array2[], int size)
{
int i;
for (i=0;i<size;i++)
{
if(array1[i] == array2[size-1])
return 0;
else
return 1;
}
}
i keep getting an error. whats wrong with it.
When you return from within any block in the function the function execution ends there, so in your case you are returning from function even when the first elements of the arrays are matching which is not correct, you should check whole array and then return from the function in the end, check the code below:
int isReverse(int array1[], int array2[], int size)
{
int i,status=1;
for (i=0;i<size;i++) //Size is the length of the array? if yes than you need -1 from it.
{
if(array1[i] == array2[size])
{
status=0;
--size;
}
else
return 1;
}
return status;
}
Moreover, size-1 does not change the value of the variable size itself hence size will remain same throughout the loop, use --size this will decrement the value of actual variable hence decrementing it by one every time.
The variable "size" never changes, so you're always checking elements of array1 against the last element of array2.
Since this sounds like a homework problem, I'll let you see if you can go from there.
This is how I did it.
int isReverse(int array1[], int array2[], int SIZE)
{
for( int counter = 0; counter <= SIZE/2; counter++ )
if(array1[counter] != array2[SIZE-counter] || array2[counter] != array1[SIZE-counter])
return 1;
return 0;
}
You are just comparing the value at index i with a constant SIZE-1. Instead you want to compare the value at i with the comparison array's size-i. So each time the counter increments it compares with the opposite array's size-i. And you only have to do this for half of the array.
The return value is wrong because you are checking only 1 value from each array, not all of them. What you want to do is something like this.
for (i=0;i<size;i++)
{
if(!(array1[i] == array2[size-i-1]))
return 0;
}
return 1;
Basically you go through the array one by one, if any of the values are not the same as the appropriate value on the other array, it is not a reverse, so we return 0. If we get out of the for loop without going through the if, it means they are reverses so we return 1.
int isReverse(int array1[], int array2[], int size)
{
int flag = 0;
for (int i=0;i<size;i++)
{
if(array1[i] != array2[size-1]){
flag = 1;
break;
}
return flag;
}
}
In the code you have kept the return statement inside the loop... keep the return statement outside the loop and try
int isReverse(int a[], int b[], int n)
{
int i = 0;
while (i<n)
{
if (a[i] != b[n-i-1]) {return 0; break;}
else i++;
}
return 1;
}
anw this was the correct answer.
bool isReverse(int array1[], int array2[],int size)
{
int i=0;
for (int k=0;k<size;k++){
if (array1[k]==array2[size-k-1]){
i++;
}
}
if (i==size){
return true;
}else{
return false;
}
}

Resources