Merge Sort-Segmentation fault - c

I have written a program in C for the Merge Sort but I get a Segmentation Fault and I don't know why? Could you give me a hint what could be wrong?
That's the code:
#include <stdio.h>
#include <math.h>
void Merge(int A[],int p,int q,int r){
int n1,n2,i,j,k;
n1=q-p+1;
n2=r-q;
int L[n1],R[n2];
for (i=0; i<n1; i++) L[i]=A[p+i-1];
for (j=0; j<n2; j++) R[j]=A[q+j];
i=0;
j=0;
for (k=p; k<r; k++){
if (L[i]<=R[j]){
A[k]=L[i];
i=i+1;
}
else{
A[k]=R[j];
j=j+1;
}
}
}
void Sort(int A[],int p,int r){
int q;
if (p<r){
q=floor((p+r)/2);
Sort(A,p,q);
Sort(A,q+1,r);
Merge(A,p,q,r);
}
}
int main()
{
int n,i,p,r;
printf("Give a value for n: \n");
scanf("%d",&n);
int A[n];
for (i=0; i<n; i++){
printf ("Give %d th value of the array: \n",i+1 );
scanf("%d",&A[i]);
}
printf("Give me a value for p:\n");
scanf("%d",&p);
printf("Give me a value for r:\n");
scanf("%d",&r);
Sort(A,p,r);
printf("p=%d, r=%d \n \n", p,r);
for (i=0; i<n; i++) printf("%d", A[i]);
return 0;
}
That's what I got,giving inputs at the terminal:
Give a value for n:
8
Give 1 th value of the array:
1
Give 2 th value of the array:
6
Give 3 th value of the array:
5
Give 4 th value of the array:
3
Give 5 th value of the array:
5
Give 6 th value of the array:
4
Give 7 th value of the array:
2
Give 8 th value of the array:
7
Give me a value for p:
2
Give me a value for r:
6
Segmentation fault (core dumped)
Have I done maybe something wrong at the function Sort?

A probable culprit is these two lines:
int n1,n2,i,j,k;
int L[n1],R[n2];
In the first you declare n1 and n2, but don't initialize them. That means their value is indeterminate and that you should not use those variable until you have initialized them.
However, in the next line you use them anyway and that causes undefined behavior which means your whole program is ill-formed and can not be relied upon to work properly.

Your n1 and n2 variables in function Merge are undefined prior to you instantiating variables L[] and R[].
Try this:
int n1, n2, i, j, k;
n1 = q - p + 1;
n2 = r - q;
// Now you can instantiate your arrays
int L[n1], R[n2];

#include<stdio.h>
void mergesort(int a[],int beg,int end)
{
int mid;
if(beg<end)
mid = (beg+end)/2;
mergesort(a,beg,mid);
mergesort(a,mid+1,end);
merge(a,beg,mid,end);
}
void merge(int a[],int beg,int mid,int end)
{
int i=beg,j=mid+1,index=beg,temp[100],k;
while((i<=mid) && (j<=end))
{
if(a[i]<a[j])
{
temp[index]=a[i];
i=i+1;
}
else
{
temp[index]=a[j];
j++;
}
index++;
}
if(i>mid)
{
while(j<=end)
{
temp[index]=a[j];
j++;
index++;
}
}
else
{
while(i<=mid)
{
temp[index]=a[i];
i++;
index++;
}
}
for(k=beg;k<index;k++)
{
a[k]=temp[k];
}
}
int main()
{
int a[100],n,i,j;
printf("enter size of array");
scanf("%d",&n);
printf("enter elements");
for(i=0;i<n;i++)
{
scanf("%d",&a[i]);
}
mergesort(a,0,n-1);
for(i=0;i<n;i++)
{
printf("5d",a[i]);
}
return 0;
}

Related

Adding the same number multiple times to an empty array in C

This is a piece of code to add the same number multiple times to an empty array but when I am printing the now non empty array, I am getting some other values:
#include<stdio.h>
#include<stdlib.h>
void sort_0(int arr[100], int i, int n){
int final_array[100], c=0;
// Count the number of '0' in the array
for(i=0;i<n;i++){
if(arr[i] == 0){
c++;
}
}
// Add the c number of '0' to the final_array
for(i=0;i<c;i++){
scanf("%d",final_array[i]);
}
for(i=0;i<c;i++){
printf("%d ", final_array[i]);
}
}
int main(){
int arr[100], i, n;
// Entering the size of the array
scanf("%d", &n);
// Entering n elements into the array
for(i=0;i<n;i++){
scanf("%d", &arr[i]);
}
sort_0(arr,i,n);
return 0;
}
In the above code, the number of times 0 appears in the array is counted. Then the count is taken as the range and 0 is adding to the empty array final_array count times.
If c = 5, the final_array = {0,0,0,0,0}
Expected Output:
arr = {0,1,4,3,0}
Output = 2
I am not getting any output
Since you don't know how much 0 you'll need to add to your array_final I figured out that a better solution could be to create that array after you have the number of 0 of the first array. Also, I see no reason why you were passsing i to the function since you can simply define it in the function itself.
void sort_0(int arr[10], int n, int* c){
int i;
for(i=0;i<n;i++){
if(arr[i] == 0){
(*c)+= 1;
}
}
}
int main (void) {
int size;
printf("Enter array size: ");
scanf("%d", &size);
int arr[size];
for (int i=0;i<size;i++) {
scanf("%d",&arr[i]);
}
int c = 0;
sort_0(arr, size, &c);
printf("C is: %d\n",c);
int* final_array;
if ((final_array=malloc(c * sizeof(int)))==NULL) // should always check malloc errors
{
perror("malloc");
return -1;
}
for (int i=0;i<c;i++) {
final_array[i]= 0;
}
printf("{");
for (int i=0;i<c-1;i++) {
printf("%d,", final_array[i]);
}
printf("%d}\n",final_array[c-1]);
return 0;
}

Chef and Dolls MISSP

Here is the link to the codechef problem - Chef and Dolls
Why does my code always print the wrong answer? The output should be the number which doesn't have a match but my code always print the first element. Coudn't get the conditions right, what should be the condition?
Problem Statement
Chef is fan of pairs and he likes all things that come in pairs. He even has a doll collection in which all dolls have paired.One day while going through his collection he found that there are odd number of dolls. Someone had stolen a doll!!!
Help chef find which type of doll is missing..
Input
The first line contains the number of test cases.
Second line of the input contains the number of elements in the array.
The next n lines are the types of each doll that is left.
Output
Find the type of doll that doesn't have a pair
Example
Input:
1
3
1
2
1
Output:
2
#include <stdio.h>
int main(){
int t, N, i, m, k, z, flag=0;
scanf("%d", &t);
while(t--)
{
scanf("%d",&N);
int arr[N];
for(i=0;i<N;i++){
scanf("%d", &arr[i]);
}
int j;
for(j=0;j<N;j++){
m=arr[j];
for(k=0;k<N;k++){
if(m==arr[k] && k!=j)
{
flag=0;
}
else
{
flag=1;
break;
}
printf("%d", m);
}
}
}
return 0;
}
You break out of your loop everytime k==j. You have to check for every array member if it is present somewhere else in the array.
#include <stdio.h>
int main()
{
int t, N, i, j, k, m, z, flag;
scanf("%d", &t);
while(t--)
{
scanf("%d",&N);
int arr[N];
for(i=0;i<N;i++)
{
scanf("%d", &arr[i]);
}
for(j=0;j<N;j++)
{
m=arr[j];
flag=1;
for(k=0;k<N;k++)
{
if(m==arr[k] && k!=j)
{
flag=0;
}
}
if(flag)
{
printf("%d\n", m);
}
}
}
return 0;
}
But be careful as this only looks if an array member has a duplicate in it. You probably want to check if there is an even number of elements in the array.
If you want to check which array members occur an odd number of times
#include <stdio.h>
int main()
{
int t, N, i, j, k, m, z, num, flag;
scanf("%d", &t);
while(t--)
{
scanf("%d",&N);
int arr[N], odds[N], n_odds;
for(i=0;i<N;i++)
{
scanf("%d", &arr[i]);
}
n_odds=0;
for(j=0;j<N;j++)
{
m=arr[j];
num=0;
for(k=0;k<N;k++)
{
if(m==arr[k])
{
num++;
}
}
if(num%2) //occurs an odd number of times
{
flag=1;
for(i=0;i<n_odds;i++)
{
if(m==odds[i]) //has already been checked
{
flag=0;
}
}
if(flag)
{
printf("%d\n", m);
odds[n_odds++]=m;
}
}
}
}
return 0;
}

MergeSort giving Segmentation fault

I used this merge sort program to create my own program:
https://gist.github.com/mycodeschool/9678029
my program gives me segmentation fault 11. I can't seem to figure out what's wrong. Please help me.
my program:
#include<stdio.h>
int a[20],n, nl, nr,left[20],right[20];
void merge(int *l, int *r, int *x);
void mergesort(int *x, int v);
void main()
{
int i;
printf("Enter the number of the elements \n");
scanf("%d", &n);
printf("Enter the array elements \n");
for(i=0; i<n; i++)
scanf("%d", &a[i]);
printf("The array before sorting: \n");
for(i=0; i<n; i++)
printf("%d \n", a[i]);
mergesort(a,n);
printf("The array after sorting: \n");
for(i=0; i<n; i++)
printf("%d \n", a[i]);
}
void merge(int *l, int *r, int *x)
{
int i=0, j=0, k=0;
while(i<nl && j<nr)
{
if(l[i]<=r[j])
{
x[k]=l[i];
i++;
}
else
{
x[k]=r[j];
j++;
}
k++;
}
while(i<nl)
{
x[k]=l[i];
i++;
k++;
}
while(j<nr)
{
x[k]=r[j];
j++;
k++;
}
}
void mergesort(int *x, int v)
{
int mid,i;
if(n<2)
return;
mid=n/2;
nl=mid;
nr= n-mid;
for(i=0; i<mid; i++)
left[i]=x[i];
for(i=mid; i<n; i++)
right[i-mid]= x[i];
mergesort(left, mid);
mergesort(right,v-mid);
merge(left, right, a);
}
I would really appreciate if someone helped me. Thanks!
here is an example of a merge sort program, easily found via a google of the web.
Some comparison should show you where your code went wrong.
#include<stdio.h>
void mergesort(int a[],int i,int j);
void merge(int a[],int i1,int j1,int i2,int j2);
int main()
{
int a[30],n,i;
printf("Enter no of elements:");
scanf("%d",&n);
printf("Enter array elements:");
for(i=0;i<n;i++)
scanf("%d",&a[i]);
mergesort(a,0,n-1);
printf("\nSorted array is :");
for(i=0;i<n;i++)
printf("%d ",a[i]);
return 0;
}
void mergesort(int a[],int i,int j)
{
int mid;
if(i<j)
{
mid=(i+j)/2;
mergesort(a,i,mid); //left recursion
mergesort(a,mid+1,j); //right recursion
merge(a,i,mid,mid+1,j); //merging of two sorted sub-arrays
}
}
void merge(int a[],int i1,int j1,int i2,int j2)
{
int temp[50]; //array used for merging
int i,j,k;
i=i1; //beginning of the first list
j=i2; //beginning of the second list
k=0;
while(i<=j1 && j<=j2) //while elements in both lists
{
if(a[i]<a[j])
temp[k++]=a[i++];
else
temp[k++]=a[j++];
}
while(i<=j1) //copy remaining elements of the first list
temp[k++]=a[i++];
while(j<=j2) //copy remaining elements of the second list
temp[k++]=a[j++];
//Transfer elements from temp[] back to a[]
for(i=i1,j=0;i<=j2;i++,j++)
a[i]=temp[j];
}

output different elements from two arrays

I am trying to output different elements from two arrays. So if i have an array A: {9, 0, 1} and B is {0, 8, 1}, I need to output an element which included in the first set, but are not included in the second :9 Can not think how I should compare all elements from the first array with the second one.
#include <stdio.h>
#include <stdlib.h>
int main()
{
int a[10],b[10],c,n,i,j;
printf("enter a number: ");
scanf("%d",&n);
for(i=0;i<n;i++){
printf("Enter a[%d]: ",i+1);
scanf("%d",&a[i]);
}
printf("\n");
for(j=0;j<n;j++){
printf("Enter b[%d]: ",j+1);
scanf("%d",&b[j]);
}
for (i = 0; i < n; i++) {
printf("%d ", a[i]); }
printf("\n");
for (i = 0; i < n; i++) {
printf("%d ", b[i]); }
printf("\n");
return 0;
}
I'd like to show my thoughts but i think it's stupid:
for(i=0;i<n;i++){
for(j=0;j<n;j++){
if(a[i]!= b[j]){
c=a[i];
}
}
printf("%d ",c);
}
This can be easily solved using Binary search. Follow the simple steps.
Step 1: Sort the second array.
Step 2: For each element of the first array, binary search it in the second array, if its not present , print it, otherwise dont.
The time complexity is O(m log n), where m is length of first array and n is length of second array.
If you want a more efficient solution, as suggested by #Sumeet Singh, you can sort the second array with qsort, then find similar elements from the first array with bsearch(binary search).
Your current solution is O(N^2) time, which will be very slow with large n, but you can achieve more efficiency with this approach.
Here is some code I wrote up with demonstrates this:
#include <stdio.h>
#include <stdlib.h>
#define NNUMBERS 10
void get_array_input(int array1[], int array2[], size_t *n);
void search_elements(int array1[], int array2[], size_t n);
void print_arrays(int array[], size_t n);
int cmp_func(const void *a, const void *b);
int main(void) {
int array1[NNUMBERS], array2[NNUMBERS];
size_t n;
/* input from user */
get_array_input(array1, array2, &n);
printf("\nFirst array: ");
print_arrays(array1, n);
printf("\nSecond array: ");
print_arrays(array2, n);
/* sorting the second array */
qsort(array2, n, sizeof(*array2), cmp_func);
printf("\nSorted Second array: ");
print_arrays(array2, n);
/* the search begins */
search_elements(array1, array2, n);
return 0;
}
void get_array_input(int array1[], int array2[], size_t *n) {
size_t i;
printf("Enter n: ");
if (scanf("%zu", n) != 1) {
printf("Invalid n value.\n");
exit(EXIT_FAILURE);
}
for (i = 0; i < *n; i++) {
printf("Enter array1[%zu]: ", i);
if (scanf("%d", &array1[i]) != 1) {
printf("Invalud array value.\n");
exit(EXIT_FAILURE);
}
}
for (i = 0; i < *n; i++) {
printf("Enter array2[%zu]: ", i);
if (scanf("%d", &array2[i]) != 1) {
printf("Invalud array value.\n");
exit(EXIT_FAILURE);
}
}
}
void search_elements(int array1[], int array2[], size_t n) {
size_t i;
void *key;
printf("\nElements in first array which are not in second array: ");
for (i = 0; i < n; i++) {
key = bsearch(&array1[i], array2, n, sizeof(*array2), cmp_func);
if (!key) {
printf("%d ", array1[i]); /* not found, so print it */
}
}
printf("\n");
}
void print_arrays(int array[], size_t n) {
size_t i;
for (i = 0; i < n; i++) {
printf("%d ", array[i]);
}
printf("\n");
}
/* cmp function needed for qsort and bsearch */
/* many ways to write these */
int cmp_func(const void *a, const void *b) {
const int *num1 = (const int *)a;
const int *num2 = (const int *)b;
if (*num1 > *num2) {
return +1;
} else if (*num1 < *num2) {
return -1;
}
return 0;
}
Input:
Enter n: 3
Enter array1[0]: 9
Enter array1[1]: 0
Enter array1[2]: 1
Enter array2[0]: 0
Enter array2[1]: 8
Enter array2[2]: 1
Output:
First array: 9 0 1
Second array: 0 8 1
Sorted Second array: 0 1 8
Elements in first array which are not in second array: 9
You are on the right path. You are taking each value from the first array and comparing to each value in the second.
What you need to do now is to only print a[i] if there isn't any b[j] such that they are the same. The easiest way is to set a flag (say, unique=1). You can give this flag any name you find suitable, but in this case I'm thinking it says that the number a[i] is "unique" to the array a. So in this case you start with the premise that, yes, you won't find a[i] in the arrayb, and then you try to disprove your assumption. If at any time of you search you find an instance of a[i] == b[j], then your premise was wrong, so you set unique=0.
After you have compared this a[i] against all elements in b, you review your flag. And you print the appropriate message depending on whether you found this element in b or not.
Note that this assumes that the same value doesn't appear twice in a.
I have edited your code a little bit and this code gives you desired output:
#include <stdio.h>
int main(void){
int a[10],b[10],c,n,i,j;
int counter=0;
printf("enter a number: ");
scanf("%d",&n);
for(i=0;i<n;i++){
printf("Enter a[%d]: \n",i+1);
scanf("%d",&a[i]);
}
printf("\n");
for(j=0;j<n;j++){
printf("Enter b[%d]: \n",j+1);
scanf("%d",&b[j]);
}
for(i=0;i<n;i++){
counter=0;
for(j=0;j<n;j++){
if(a[i]!=b[j]){
counter++;
}
}
if(counter == n){
printf("%d ",a[i]);
}
}
return 0;
}
Let's explain this code a little bit:
In the last nested for loop, outer loop takes one element from array a. Inner loop gets every element of array b in order to compare it to taken element from array a. If none of the elements of array b is equal to a's taken element, counter will be equal to n(array size). Then we can print this element taken from a(it means there is no match between this taken element and array b's all of elements.

Reverse array with recursion in C programming

I was having some problem when trying to do a reverse array using recursion. Here is the function prototype:
void rReverseAr(int ar[ ], int size);
And here is my code:
int main()
{
int ar[10], size, i;
printf("Enter array size: ");
scanf("%d", &size);
printf("Enter %d numbers: ", size);
for (i = 0; i<size; i++)
scanf("%d", &ar[i]);
rReverseAr(ar, size);
printf("rReverseAr(): ");
for (i = 0; i<size; i++)
printf("%d ", ar[i]);
return 0;
}
void rReverseAr(int ar[], int size) {
int start = 0, end = size - 1, temp;
if (start < end) {
temp = ar[start];
ar[start] = ar[end];
ar[end] = temp;
start++;
end--;
rReverseAr(ar, size - 1);
}
}
The expected output should be when user entered 1 2 3 and it supposed to return 3 2 1. However, with these code, the output that I am getting is 2 3 1.
Any ideas?
Your code is almost right. The only problem is that instead of "shrinking" the array from both sides, you shrink it only from the back.
The recursive invocation should look like this:
rReverseAr(ar + 1, size - 2);
You do not need to increment start or decrement end, because their values are not used after modification.
A Simple way :
#include<stdio.h>
using namespace std;
void revs(int i, int n, int arr[])
{
if(i==n)
{
return ;
}
else
{
revs(i+1, n, arr);
printf("%d ", arr[i]);
}
}
int main()
{
int i, n, arr[10];
scanf("%d", &n);
for(i=0; i<n; i++)
{
scanf("%d", &arr[i]);
}
revs(0, n, arr);
return 0;
}
Iterate array with recursion in C : link
What you are doing is to exchange values of the 1st and last elements and do the recursion.
Every time you should move your address to the next element as the starter for the next array exchange.
A possible way:
void rReverseAr(int ar[], int size){
int buffer=ar[0];
ar[0] = ar[size-1];
ar[size-1] = buffer;
if ((size!=2)&&(size!=1)) rReverseAr(ar+1,size-2);
}

Resources