Merge Sort Program - c

#include<stdio.h>
#include<stdlib.h>
void merge(int a[],int l,int m,int r)
{
int i,j,k;
int n1= m - l + 1;
int n2= r - m;
int L[n1],R[n2];
for(i=0;i<n1;i++)
L[i]=a[l+i];
for(j=0;j<n2;j++)
R[j]=a[m + 1+ j];
i=0;j=0;k=l;
while(i<n1 && j<n2)
{
if(L[i]<R[j])
{
a[k]=L[i];
i++;
}
else
{
a[k]=R[j];
j++;
}
k++;
}
while(i<n1)
{
a[k]=L[i];
i++;
k++;
}
while(j<n2)
{
a[k]=R[j];
j++;
k++;
}
}
void mergeSort(int a[],int l,int r)
{
if(l<r)
{
int m = l+(r-1)/2;
mergeSort(a,l,m);
mergeSort(a,m+1,r);
merge(a,l,m,r);
}
}
void printArray(int a[],int n)
{
int i;
for(i=0;i<n;i++)
printf("%d ",a[i]);
printf("\n");
}
int main()
{
int a[]= {
12,76,34,45,63,98
};
int n = sizeof(a)/sizeof(a[0]);
printf("The element entered in array ");
printArray(a,n);
mergeSort(a,0,n-1);
printf("The element after sorting ");
printArray(a,n);
return 0;
}
This is a merge sort program. Why it's giving runtime error if anyone can explain? There is no error in this program
I have tried this 10 times. And unable to find the solution.

When you call mergesort(a, 3, 5) the following happens:
int m = l+(r-1)/2; // 3 + (5-1)/2 -> 3 + 4/2 -> 3 + 2 -> 5
mergeSort(a,l,m); // So this will call: mergesort(a, 3, 5) again
In other words: An endless loop.
Maybe you want this instead:
int m = (l+(r-1))/2;
^ ^
notice
So how did I find the bug?
Very easy - just use some printf-debug.
First I added a print in the start of mergesort - like:
void mergeSort(int a[],int l,int r)
{
printf("mergesort %d %d\n", l, r); // Debug print
if(l<r)
{
int m = (l+(r-1))/2;
mergeSort(a,l,m);
mergeSort(a,m+1,r);
merge(a,l,m,r);
}
}
and got the output:
mergesort 3 5
mergesort 3 5
mergesort 3 5
...
...
which told me that there was an endless loop for input values 3 and 5.
Then I added a print of m
void mergeSort(int a[],int l,int r)
{
printf("mergesort %d %d\n", l, r);
if(l<r)
{
int m = (l+(r-1))/2;
printf("m %d\n", m);
mergeSort(a,l,m);
mergeSort(a,m+1,r);
merge(a,l,m,r);
}
}
and got the output:
mergesort 3 5
m 5
mergesort 3 5
m 5
mergesort 3 5
m 5
so obviously m was calculated wrongly.
Looking close at
int m = l+(r-1)/2;
is was clear that the addition should be before the division. A set of (....) was missing.
Hope you can use this debug example for your own debug.

Related

Hoare partition correctness

according to introduction to algorithms I wrote a code for quicksort using Hoare's partition in the codeblocks IDE .The code was successfully built but the sorted array is not displayed on the console,only the unsorted array is displayed followed by a blinking underscore.
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
int partition(int arr[],int p,int r)
{
int i,j,x,temp;
x=arr[p];
i=p-1;
j=r+1;
while(true)
{
do{
j=j-1;
}while(arr[j]<=x);
do{
i=i+1;
}while(arr[i]>=x);
if (i<j)
{
temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
else
return j;
}
}
void quicksort(int arr[],int p,int r)
{
if (p<r)
{
int q=partition(arr,p,r);
quicksort(arr,p,q-1);
quicksort(arr,q-1,r);
}
}
void print(int A[],int size)
{
int i;
for(i=0;i<size;i++)
printf("%d ",A[i]);
}
int main()
{
int arr[]={1,12,56,2,67,0,98,23};
int size=sizeof(arr)/sizeof(arr[0]);
printf("\nthe array is\n");
print(arr,size);
quicksort(arr,0,size-1);
printf("\nthe sorted array is\n ");
print(arr,size);
return 0;
}
the output was as follows
the array is
1 12 56 2 67 0 98 23
`
Okay, I refactored your algorithm, based on a guide from wikipedia: https://en.wikipedia.org/wiki/Quicksort
As mentioned in my comment above, the [recursive] quicksort calls used the wrong arguments. But, then, as Weather Vane mentioned, it [still] didn't sort.
Edit: My original post was using Lomuto partitioning instead of Hoare.
The partition algorithm differed from the wiki by using a different initial value for the pivot and using <=,>= on the do/while termination conditions instead of <,>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
int
partition(int arr[], int p, int r)
{
int i,
j,
x,
temp;
x = arr[(p + r) / 2];
i = p - 1;
j = r + 1;
while (1) {
do {
i += 1;
} while (arr[i] < x);
do {
j -= 1;
} while (arr[j] > x);
if (i >= j)
return j;
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
void
quicksort(int arr[], int p, int r)
{
if (p < r) {
int q = partition(arr, p, r);
quicksort(arr, p, q);
quicksort(arr, q + 1, r);
}
}
void
print(int A[], int size)
{
int i;
for (i = 0; i < size; i++)
printf("%d ", A[i]);
}
int
main()
{
int arr[] = { 1, 12, 56, 2, 67, 0, 98, 23 };
int size = sizeof(arr) / sizeof(arr[0]);
printf("\nthe array is\n");
print(arr, size);
quicksort(arr, 0, size - 1);
printf("\nthe sorted array is\n ");
print(arr, size);
printf("\n");
return 0;
}

C language: Why my code get infinite loop and how to use recursion to solve Merge Sort problem?

There are two problems I encounter in this code.
The first problem is the infinite loop, which happened from 77~79. When I change this test data and use merge method instead, I will get infinite loop and the R1 will be change to 4198739.But if I use mergeSort method, the problem won't show up as expected. Shown as below:
int M = 2;
int R1 = 4;
int arr[] = {3,9,8,20};
merge(arr, L, M, R1);
Second problem happened from 57 to 69 lines.In this mergeSort method, I tried to divide the unorder array into sub-array. However, there is no any effect on the original array.
Here is my code.
Merge Sort in C
void mergeSort(int arr[], int L, int R)
{
if(L<R) {
return ;
} else {
int M = (L+R) / 2;
mergeSort(arr, L, M);
mergeSort(arr, M+1, R);
merge(arr, L, M+1 ,R);
}
}
There are several mistakes in the logic of the code. I will address it the correct code.
A few pointers first.
The logic deals with array indices, don't confuse with array limits.
I have used sizeof operator to get the upper limit of the array.
Use if-else whenever possible.
The full code cannot be properly added here, so - https://pastebin.com/ixickcQA
Main mistake was here:
for(i=M;i<=R;i++) //1. <= as R is also an index
{
right[i-M] = arr[i];
}
here is the code linked by the (other) answer:
#include <stdio.h>
void merge(int arr[], int L, int M, int R)
{
int LEFT_SIZE = M-L;
int RIGHT_SIZE = R-M+1;
int left[LEFT_SIZE];
int right[RIGHT_SIZE];
int i,j,k;
for(i=L;i<M;i++)
{
left[i-L] = arr[i];
}
for(i=M;i<=R;i++) //1. <= as R is also an index
{
right[i-M] = arr[i];
}
i=0;
j=0;
k=L;
while(i<LEFT_SIZE && j<RIGHT_SIZE)
{
if(left[i] <= right[j]) //2. <= so that duplicates are not ignored
{
arr[k] = left[i];
i++;
}
else //3. use else to keep up the computing speed
{
arr[k] = right[j];
j++;
}
k++;
}
while(i<LEFT_SIZE)
{
arr[k] = left[i];
i++;
k++;
}
while(j<RIGHT_SIZE)
{
arr[k] = right[j];
j++;
k++;
}
}
void mergeSort(int arr[], int L, int R)
{
if(L<R) //4. Better
{
int M = (L+R) / 2;
mergeSort(arr, L, M);
mergeSort(arr, M+1, R);
merge(arr, L, M+1 ,R);
}
}
int main() {
int arr[] = {3,9,20,8,21,22};
mergeSort(arr, 0, (sizeof(arr)/sizeof(int))-1); //5. Use size-1 as we are dealing with indices
int i;
printf("Final\n");
for(i=0; i<(sizeof(arr)/sizeof(int)); i++)
{
printf("i=%d, R=%d,arr[i]=%d\n",i,(sizeof(arr)/sizeof(int)), arr[i]);
}
}
so inserting the code into an answer is no problem
In the mergeSort replace this:
if(L<R)
By this:
if(L>=R)
If L<R is present then it will always be satisfied because the index L will always be less than than R (at starting). And this is the reason that you will get infinite loop.
Your code contains a logical error on your if-statement. Try this:
void mergesort(int a[], int l, int r) {
int m;
if (l < r) {
// same as (l+r) / 2 but for avoiding overflow
m = l + (r - l) / 2;
// recur both parts
mergesort(a, l, m);
mergesort(a, m + 1, r);
merge(a, l, m, r); // merging parts
}
}

min heap program stopped working

I am doing a simple minheap program but when size of heap is 4 i get an error program stopped working.
i checked heap size 2,3,5,6,7 program is working fine.
Why am i getting this error only when heapsize is 4?
I am using codeblocks 16.01, windows 10, gcc compiler.
minHeap.c
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
void MinHeapfy(int A[], int i, int N)
{
int l,r,temp,smallest;
l = 2*i;
r = 2*i + 1;
if((l<=N) && (A[l]<A[i]))
{
smallest = l;
}
else
{
smallest = i;
}
if((r<=N) && (A[r]<A[smallest]))
{
smallest = r;
}
if(smallest != i)
{
temp = A[smallest];
A[smallest] = A[i];
A[i] = temp;
MinHeapfy(A,smallest,N);
}
}
void BuildHeap(int A[],int N)
{
int i;
int f = floor(N/2);
printf("f %d", f);
for(i=f;i>=1;i--)
{
printf("i %d\n",i);
MinHeapfy(A,i,N);
}
}
int main()
{
int *A,N,T,data,q,i=1;
scanf("%d",&N);
A = (int *)calloc(N,sizeof(int));
for(i=1;i<=N;i++)
{
scanf("%d",&data);
A[i]=data;
}
BuildHeap(A,N);
for(i=1;i<=N;i++)
{
printf("%d ",A[i]);
}
return 0;
}
I can share some things that I learned till now:
void BuildHeap(int *A, int N);
void MinHeapfy(int *A, int i, int N);
In this 2 functions you just send a pointer not an array(difference between int *A and int A[5])
int main()
{
/*here it is better for you to declare like this
to see more easier which is which pointer and variable
(PS: at the moment you don't use q)*/
int N,T,data,i;//,q
int *A;
scanf("%d",&N);
A = (int *)calloc(N,sizeof(int));
for(i=0;i<N;i++)
{
scanf("%d",&data);
A[i]=data;
}
BuildHeap(A,N);
for(i=0;i<N;i++)
{
printf("%d ",A[i]);
}
return 0;
}
The 2 fors that you use must start from 0 to N
When you write:
A[0] <=> address pointed by A + 0 * sizeof(data type of A)
So 0 is the first address of the array
and the last address is N-1
A[N-1] <=> address pointed by A + (N-1) * sizeof(data type of A)

Unable to sort Array while implementing QuickSort

I have implemented quicksort with 2 different approach taken in partition set
these are the programs
1.http://ideone.com/fPtQFT
2.http://ideone.com/KuXKr4
1.
int partition(int *a,int l,int r)
{
int i=l,pivot=l;
int j=l+1;
for(;j<r;j++)
{
if(a[j]<a[pivot])
{
swap(&a[i+1],&a[j]);
i++;
}
}
swap(&a[pivot],&a[i]);
return i;
}
2.
int partition(int *a,int l,int r)
{
int pivot=l;
int j=r-1;
int i=l+1;
while(1)
{
while(i<=j&&a[i]<=a[pivot])
i++;
while(i<=j&&a[j]>=a[pivot])
j--;
if(j<i)
break;
else
swap(&a[i],&a[j]);
}
swap(&a[pivot],&a[j]);
return j;
}
I am unable to figure out what's wrong in my code as the sorted output for example the test case
13 2 43 3 55 21 43 1 5 32
are wrong 1 2 3 13 21 32 42 5 43 55
Any help to figure out what's wrong in the logic of partitionset
The quicksort function takes the range in the form m to n where, m is the first element and n is one past the last element. This is done correctly in the main:
quicksort(a,0,N);
This means the second argument denotes the first element: 0, and the third argument denotes the one past the last element: N.
This is not done correctly in the first recursive call, where the last element is skipped because p-1 denotes the last element, instead of one past the last element:
quicksort(a,l,p-1);
Use this code to sort the array using quick sort Quick sort
QuickSort(A, P , R)
{
if(P < R)
{
Q = partition(A, P , R);
QuickSort(A, P, Q - 1);
QuickSort(A, Q + 1, R);
}
}
int partition(A, P , R)
{
while(1)
{
key = A[P];
i = P;
j = R;
while(key > A[i] && key != A[i])
i++;
while(key < A[j] && key != A[j])
j--;
if(i < j)
swap(A[i],A[j]);
else
return j;
}
}
this should do it:
#include <stdio.h>
#define N 10
void swap(int *a,int*b)
{
int temp=*b;
*b=*a;
*a=temp;
}
int partition(int *a,int l,int r)
{
int i=l,pivot=a[r];
int j=l;
for(;j<r;j++)
{
if(a[j]<pivot)
{
swap(&a[i],&a[j]);
i++;
}
}
swap(&a[i],&a[r]);
return i;
}
void quicksort(int *a,int l,int r){
int p;
if(l<r)
{
p=partition(a,l,r);
quicksort(a,l,p-1);
quicksort(a,p+1,r);
}
}
int main(){
int a[N] = {13, 2, 43, 3, 55, 21, 43, 1, 5, 32};
int i;
quicksort(a,0,N);
for(i=0;i<N;i++)
printf("%d ",a[i]);
return 0;
}

Merge Sort-Segmentation fault

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;
}

Resources