Not getting output for Merge Sort - arrays

I am trying this merge sort. But I am getting no output. Means it is giving no output on console screen even waited for 2 min. Anyone of you please help me with this. Where should I correct myself.
#include <stdio.h>
#include <stdlib.h>
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
void MergeSort();
void Merging();
int main() {
int arr[100];
int i;
for (i = 0; i < 5; i++) {
scanf("%d", &arr[i]);
}
printf("Unsorted\n");
for (i = 0; i < 5; i++) {
printf("%d ", arr[i]);
}
printf("\n");
MergeSort(arr, 0, 4);
printf("Sorted\n");
for (i = 0; i < 5; i++) {
printf("%d ", arr[i]);
}
return 0;
}
void MergeSort(int arr[], int l, int h) {
if (l < h) {
int mid = (l + h) / 2;
MergeSort(arr, l, mid);
MergeSort(arr, mid + 1, h);
Merging(arr, l, mid, h);
}
}
void Merging(int arr[], int l, int mid, int h) {
int i1 = l, i2 = mid + 1, j1 = mid, j2 = h;
int b[6];
int k = l;
while (i1 <= j1 && i2 <= j2) {
if (arr[i1] < arr[i2]) {
b[k++] = arr[i1++];
} else {
b[k++] = arr[i2++];
}
}
while (i1 <= j1) {
b[k++] = arr[i1];
}
while (i2 <= j2) {
b[k++] = arr[i2];
}
int i;
for (i = l; i <= h; i++) {
arr[i] = b[i];
}
}
I have seen in other sites using two different arrays and first storing main array values then merging two arrays. I thought of doing it different way.

You forgot about index incrementing in tail treatment in Merging.
ideone
while(i1<=j1){
b[k++] = arr[i1++];
}
while(i2<=j2){
b[k++] = arr[i2++];

The code did not execute within time limits because it encountered itself in an infinite loop.
There are a couple of changes required:
The function declaration should correctly specify the number and types of the parameters.
For the following two while loops, the value of the iterators i1 and i2 were never changed. Therefore, it caused an infinite loop and nothing was displayed on the screen.
while(i1<=j1){
b[k++] = arr[i1++];
}
while(i2<=j2){
b[k++] = arr[i2++];
}
Have a look at the following corrected code:
#include <stdio.h>
#include <stdlib.h>
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
void MergeSort(int arr[],int l,int h);
void Merging(int arr[], int l, int mid, int h);
int main(){
int arr[100];
int i;
for(i=0;i<5;i++){
scanf("%d",&arr[i]);
}
printf("Unsorted\n");
for(i=0;i<5;i++){
printf("%d ",arr[i]);
}
printf("\n");
MergeSort(arr,0,4);
printf("Sorted\n");
for(i=0;i<5;i++){
printf("%d ",arr[i]);
}
return 0;
}
void MergeSort(int arr[],int l,int h){
if(l<h){
int mid = (l+h)/2;
MergeSort(arr,l,mid);
MergeSort(arr,mid+1,h);
Merging(arr,l,mid,h);
}
}
void Merging(int arr[], int l, int mid, int h){
int i1 = l,i2 = mid+1, j1 = mid, j2 = h;
int b[6];
int k=l;
while(i1<=j1&&i2<=j2){
if(arr[i1]<arr[i2]){
b[k++] = arr[i1++];
}else{
b[k++] = arr[i2++];
}
}
while(i1<=j1){
b[k++] = arr[i1++];
}
while(i2<=j2){
b[k++] = arr[i2++];
}
int i;
for(i=l;i<=h;i++){
arr[i] = b[i];
}
}
Testing:
Input: 5 4 -1 3 1
Output:
Unsorted
5 4 -1 3 1
Sorted
-1 1 3 4 5

You forgot to increment i1 and i2 that's why it generated an infinite loop and no output was shown on console.
while(i1<=j1){
b[k++] = arr[i1++];
}
while(i2<=j2){
b[k++] = arr[i2++];

Related

How to do merge sort without using additional arrays for splitting the initial array?

I was trying to solve a problem which asks to write merge sort code but without using additional arrays for partitioning the initial array. I guess the code is wrote is almost good but the problem I am facing is that I can't figure out how to maintain and update the array while being sorted. I know the problem is in Merge function.
How can I fix the code?
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
void PrintArray(int A[], int n)
{
for(int i=0; i < n; i++)
printf("%d ", A[i]);
printf("\n");
}
void merge(int A[], int left, int mid, int right, int n){
int B[n];
int i = left, j = mid+1, k=0;
while(i<=mid && j <= right){
if(A[i]>=A[j]){
B[k++] = A[i++];
}
else {
B[k++] = A[j++];
}
}
while(i<=mid){
B[k++] = A[i++];
}
while(j<=right){
B[k++] = A[j++];
}
for(i=0; i<n; i++){
A[i] = B[i];
}
}
void MergeSort(int A[], int left, int right, int n)
{
if(left<right){
int mid;
mid = floor((left+right)/2);
MergeSort(A,left,mid,n/2);
MergeSort(A,mid+1,right,n/2);
merge(A,left,mid,right,n);
}
else return;
}
int main()
{
int n;
scanf("%d",&n);
int A[n];
for(int i=0; i < n; i++) scanf("%d", &A[i]);
MergeSort(A, 0, n-1, n);
PrintArray(A, n);
return 0;
}
In the final for loop in merge, change:
A[i] = B[i];
Into:
A[left + i] = B[i];
Edit: Even after that fix, the sort was still wrong. The correct fix for the final loop is:
for (i = left; i <= right; ++i)
A[i] = B[i - left];
The original for (i = 0; i < n; ++i) didn't work because just passing n / 2 could pass a value that was one less than needed. With this new fix, n doesn't need to be passed to merge at all. So, n is really only needed for the public function. See the UPDATE section below.
Side notes:
You don't need to use floor at all. It's superfluous for integer math [and might make the results less accurate].
You are sorting in reverse order (e.g. 3, 2, 1 instead of 1, 2, 3). To sort in ascending order, in merge, change: if (A[i] >= A[j]) to if (A[i] <= A[j])
You are not creating an initial extra array, but you have B on the stack in merge, so, you are using an auxiliary/temp array. This is true regardless whether you copy from A to B at the start of merge or copy back from B to A at the end of merge
So, you don't have a true "in-place" algorithm.
In fact, for large enough arrays, having B on the stack would cause a stack overflow. It might be better to use a heap allocation for B.
You could put this in a global/public "wrapper" function for mergeSort (e.g. mergeSortPublic). Do (e.g.) B = malloc(sizeof(int) * n) at the start and do free(B) at the end. You can make B global scope or pass it as an extra arg to your merge functions
UPDATE:
Here's a fully cleaned up version that adds diagnostic tests.
Because of the change in the final loop in merge, it no longer needs the n value. So, it's no longer needed in mergeSort either with the mergeSortPub change.
I refactored the first loop in merge to be slightly faster by not refetching already fetched array values. The optimizer might have found this speedup, but I think it's better to state it explicitly.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
void
PrintArray(int A[], int n)
{
int totlen = 0;
for (int i = 0; i < n; i++) {
totlen += printf(" %d", A[i]);
if (totlen >= 72) {
printf("\n");
totlen = 0;
}
}
if (totlen > 0)
printf("\n");
}
void
merge(int A[], int left, int mid, int right, int *B)
{
int i = left,
j = mid + 1,
k = 0;
int Ai = A[i];
int Aj = A[j];
while (i <= mid && j <= right) {
if (Ai <= Aj) {
B[k++] = Ai;
Ai = A[++i];
}
else {
B[k++] = Aj;
Aj = A[++j];
}
}
while (i <= mid)
B[k++] = A[i++];
while (j <= right)
B[k++] = A[j++];
// original code
#if 0
for (i = 0; i < n; i++)
A[i] = B[i];
#endif
// first fix -- still broken
#if 0
for (i = 0; i < n; i++)
A[left + i] = B[i];
#endif
// correct fix
#if 1
for (i = left; i <= right; ++i)
A[i] = B[i - left];
#endif
}
void
MergeSort(int A[], int left, int right, int *B)
{
if (left < right) {
int mid = (left + right) / 2;
MergeSort(A, left, mid, B);
MergeSort(A, mid + 1, right, B);
merge(A, left, mid, right, B);
}
}
void
MergeSortPub(int A[], int n)
{
int *B = malloc(sizeof(*B) * n);
MergeSort(A,0,n - 1,B);
free(B);
}
void
dotest(int tstno)
{
int n = rand() % 1000;
int *A = malloc(sizeof(*A) * n);
for (int i = 0; i < n; ++i)
A[i] = n - i;
MergeSortPub(A,n);
int old = A[0];
int bad = 0;
for (int i = 1; i < n; ++i) {
int cur = A[i];
if (cur < old) {
if (! bad)
printf("dotest: %d -- i=%d old=%d cur=%d\n",tstno,i,old,cur);
bad = 1;
}
old = cur;
}
if (bad) {
PrintArray(A,n);
exit(1);
}
}
int
main(void)
{
int n;
#if 0
scanf("%d", &n);
int A[n];
for (int i = 0; i < n; i++)
scanf("%d", &A[i]);
MergeSortPub(A, n);
PrintArray(A, n);
#else
for (int tstno = 1; tstno <= 1000; ++tstno)
dotest(tstno);
#endif
return 0;
}
There are a few variations of merge sort that do not use any additional space other than local variables. Optimal implementations of this are complicated and about 50% slower than conventional merge sort, and most of these implementations are for academic research.
There is a wiki article for one variation, that is hybrid of insertion and merge sort.
https://en.wikipedia.org/wiki/Block_sort
Link to a more optimized version in grailsort.h in this github repository. The void GrailSort(SORT_TYPE *arr,int Len) function does not use any additional buffer.
https://github.com/Mrrl/GrailSort

How to get subsets of a set with given number of elements in C with recursion?

For instance when user input 4 and 2, it means the original set have 4 elements: (1,2,3,4) and the subset should have 2 elements. I figured out a way to present these subsets in a regular form like (1,2)(1,3)(1,4)(2,3)(2,4)(3,4) using the code below, but my assignment requires binary-like form like (1,2) should be (1,1,0,0) and (2,4) should be (0,1,0,1) etc. In (1,1,0,0), first binary 1 means the first element in original set (1,2,3,4) which is 1 is contained in the subset. And the second binary 1 means the second element in original set which is 2 is contained in subset. While the third and forth number 3 and 4 is not. So for example, a subset (1,2,5) from set (1,2,3,4,5) can be presented by (1,1,0,0,1)
void subset(int n, int k, int B[], int q, int r) {
if (q == k) {
for (int i = 0; i < k; i++) {
printf("%d ", B[i]);
}
printf("\n");
} else {
for (int i = r; i < n; i++) {
B[q] = i+1;
subset(n, k, B, q+1, i+1);
}
}
}
In main (n is number of elements in original set, k is number of elements in subsets):
int B[101];
subset(n, k, B, 0, 0);
Also my assignment needs this recursive function with 4 exact arguments( i is from (1,2,3,4...i) ):
void subsets(int B[], int n, int k, int i)
I've tried so many ways and failed. I'll be really appreciated if someone can help me out, thanks.
Updates:
thanks to rajender kumar, the binary-like output problem is solved by using the code below:
void printSubsets(int B[], int n, int k, int q, int i) {
if (q == k) {
int finalArry[MAX_SIZE+1] = {0};
for (int i = 0; i < k; i++) {
finalArry[B[i]] = 1;
}
printSet(finalArry, n);
} else {
for (int j = i; j < n; j++) {
B[q] = j+1;
printSubsets(B, n, k, q+1, j+1);
}
}
}
But I still need to remove one argument from either int q or int i.
This should do the job:
void subset(int n, int k, int B[], int i) {
if (k == 0) {
for (int d = 0; d < n; d++) {
printf("%d ", B[d]);
}
printf("\n");
} else if (i >= n || k > n - i) {
return;
} else {
B[i] = 1;
subset(n, k - 1, B, i + 1);
B[i] = 0;
subset(n, k, B, i + 1);
}
}
int main(int argc, char **argv) {
int n, k;
int B[4];
memset(B, 0, sizeof(B));
n = sizeof(B) / sizeof(B[0]);
k = 2;
printf("n=%d\nk=%d\n", n, k);
subset(n, k, B, 0);
return 0;
}
Add another boolean array and put entire array like this .
void subset(int n, int k, int B[], int q, int r) {
if (q == k) {
bool finalArry[n] = {0};
for (int i = 0; i < k; i++) {
finalArry[B[i]-1] = true;
}
for (int i = 0; i < n; i++) {
if(finalArry[i]){
cout<<1<<" ";
}
else{
cout<<0<<" ";
}
}
cout<<endl;
} else {
for (int i = r; i < n; i++) {
B[q] = i+1;
subset(n, k, B, q+1, i+1);
}
}
}

mergesort using C , the output goes wrong

I wrote the code in CodeBlocks 17.0.1
It seems that it only sorts some elements in the array, not all. Also, I can't find the differences between my code and the sample that I have and still don't know what goes wrong. Thank you for your help!
#include <stdio.h>
#include <stdlib.h>
void merge(float x[], float y[], int l, int m, int r)
{
int ptr_1,ptr_2,ptr_y;
ptr_1 = ptr_y = l;
ptr_2 = m+1;
while((ptr_1<=m) && (ptr_2<=r))
{
if(x[ptr_1] <= x[ptr_2])
y[ptr_y++] = x[ptr_1++];
else
{
y[ptr_y++] = x[ptr_2++];
}
}
while(ptr_1<=m)
y[ptr_y++] = x[ptr_1++];
while(ptr_2<=r)
y[ptr_y++] = x[ptr_2++];
}
void merge_sort(float a[],float b[],int l, int r)
{
if(l < r)
{ int m = l + (r-l)/2;
merge_sort(a,b,l,m);
merge_sort(a,b,m+1,r);
merge(a,b,l,m,r);
}
}
int main()
{
float a[3] ={10.3,8.5,3.23},b[3];
int i,j;
float *temp = b;
merge_sort(a,temp,0,2);
for(i=0;i<3;i++)
{
printf("%.2f ",b[i]);
}
printf("\n");
system("pause");
return 0;
}
Output: 3.23 10.30 8.50
Here is the working code:
#include <stdio.h>
#include <stdlib.h>
void merge(float a[], int l, int m, int r)
{
int i, j, k;
int n1 = m - l + 1;
int n2 = r - m;
/* create temp arrays */
float L[n1], R[n2];
/* Copy data to temp arrays L[] and R[] */
for (i = 0; i < n1; i++)
L[i] = a[l + i];
for (j = 0; j < n2; j++)
R[j] = a[m + 1+ j];
/* Merge the temp arrays back into arr[l..r]*/
i = 0; // Initial index of first subarray
j = 0; // Initial index of second subarray
k = l; // Initial index of merged subarray
while (i < n1 && j < n2)
{
if (L[i] <= R[j])
{
a[k] = L[i];
i++;
}
else
{
a[k] = R[j];
j++;
}
k++;
}
/* Copy the remaining elements of L[], if there
are any */
while (i < n1)
{
a[k] = L[i];
i++;
k++;
}
/* Copy the remaining elements of R[], if there
are any */
while (j < n2)
{
a[k] = R[j];
j++;
k++;
}
}
void merge_sort(float a[],int l, int r)
{
if(l < r)
{ int m = l + (r-l)/2;
merge_sort(a,l,m);
merge_sort(a,m+1,r);
merge(a,l,m,r);
}
}
int main()
{
float a[3] ={10.3,8.5,3.23};
int i,j;
merge_sort(a,0,2);
for(i=0;i<3;i++)
{
printf("%.2f ",a[i]);
}
printf("\n");
system("pause");
return 0;
}
still don't know what goes wrong
Why were you using two different arrays?
Just one array is enough but it includes two logical arrays and the indexes l and m refer to the beginning of each array.
Add the code shown below to the end of merge to copy the data back. There are more efficient ways to do this that avoid the copy back step, but at least this fixes the code.
void merge(float x[], float y[], int l, int m, int r)
{
/* after the last line in merge, (y[ptr_y++] = x[ptr_2++];) */
/* add this code to copy from y[] back to x[] */
for(ptr_1 = l; ptr_1 <= r; ptr1++)
x[ptr_1] = y[ptr_1];
}

Mergesort bug + warnings

I have the following code, followed it form a tutorial, and it doesn't seem to do anything. I tried debugging it with KDB but I can't find the problem why it doesn't sort.
Maybe someone on here can help me, thanks in advance!
#include <stdio.h>
#include <stdlib.h>
void Mergesort(int *a, int length) {
int i = 0;
int mid = 0;
int *L, *R;
mid = length / 2;
if (length < 2)
return;
else {
L = (int*)malloc(sizeof(int) * mid);
R = (int*)malloc(sizeof(int) * (length - mid));
for (i = 0; i < mid; i++) {
L[i] = a[i];
}
for (i = mid; i < length; i++) {
R[i - mid] = a[i];
}
Mergesort(L, mid);
Mergesort(R, length - mid);
Merge(a, L, R, length);
}
}
void Merge(int *a, int *L, int *R, int length) {
int i = 0, j = 0, k = 0;
int mL, mR;
mL = length / 2;
mR = length - mL;
while (i < mL && j < mR) {
if (L[i] < R[j]) {
a[k] = L[i];
i++;
} else {
a[k] = R[j];
j++;
}
k++;
}
while (i < mL) {
a[k] = L[i];
i++;
k++;
}
while (j < mR) {
a[k] = R[j];
i++;
k++;
}
}
void main() {
int a[7] = { 5, 4, 99, 13, 34, 54, 2 };
int u = 0;
Mergesort(a, 7); // call to Mergesort
for (u = 0; u < 7; u++) {
printf(" %d\t", a[u]);
}
printf("\n\n\n");
}
I would really appreciate it since I need to understand it before Thursday next week :P
Here you're incrementing i but you should increment j in Merge function.
while(j<mR)
{
a[k]=R[j];
j++;
k++;
}
Edit:
put function declation after the header files void Merge(int *a,int *L,int *R,int length); otherwise you will get implicit declaration of function ‘Merge’ warning.
#include<stdio.h>
#include<stdlib.h>
void Merge(int *a,int *L,int *R,int length);
//rest of your code

Why is this program giving a stack overflow?

My C merge code works when I initialize the array globally at the top of the program until the stack overflows. I'm trying to initialize the array with malloc, but when I do, the code will only read in two integers and stop running.
This program pulls random numbers from a file called alg.txt and then sorts them. Again, the code works (up until 500k integers) when defining z at the top of the program to the number of integers to be sorted, and declaring the array globally to be equal to arr[z]. How do I figure out what is going on?
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int count = 0;
void merge(int arr[], 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] = arr[l + i];
count++;
for (j = 0; j < n2; j++)
R[j] = arr[m + 1+ j];
count++;
i = 0;
j = 0;
k = l;
while (i < n1 && j < n2)
{
if (L[i] <= R[j])
{
arr[k] = L[i];
i++;
count++;
}
else
{
arr[k] = R[j];
j++;
count++;
}
k++;
count++;
}
while (i < n1)
{
arr[k] = L[i];
i++;
k++;
count++;
}
while (j < n2)
{
arr[k] = R[j];
j++;
k++;
count++;
}
}
void mergeSort(int arr[], int l, int r)
{
if (l < r)
{
int m = l+(r-l)/2;
mergeSort(arr, l, m);
mergeSort(arr, m+1, r);
merge(arr, l, m, 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;
FILE *myFile;
myFile = fopen("alg.txt", "r");
int z;
printf("Enter the size of the array: ");
scanf("%d", &z);
int *arr = (int *)malloc(z*sizeof(int));
int n = sizeof(arr)/sizeof(arr[0]);
for(i=0; i < z; i++)
{
fscanf(myFile, "%d,", &arr[i]);
}
mergeSort(arr, 0, n - 1);
printf("\nSorted array is \n");
printArray(arr, n);
printf("count is %d\n", count);
return 0;
}
You are declaring the L and R array's locally (inside the merge function). They consume stack on every function call. You should initialize them globally so that they can be stored on the heap. Also, you should declare just one array (like temp_arr in the below code) as there's no need for two separate arrays like L and R.
See Local vs Global variable storage
You can improve your merge function to this:
int temp_arr[500000]; // Global declaration
void merge(int arr[], int l, int m, int r)
{
int i=l, j=m+1, k=l;
while(i<=m && j<=r)
{
if(arr[i]<arr[j])
temp_arr[++k] = arr[++i];
else temp_arr[++k] = arr[++j];
}
while(i<=m)
temp_arr[++k] = arr[++i];
while(j<=r)
temp_arr[++k] = arr[++j];
i = l;
while(i<=r)
arr[i] = temp_arr[++i]; // Storing stored array in arr
}

Resources