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];
}
Related
Comparing the running time of these two sorts, for some reason I get that they work in almost the same time, and on sorted arrays, shell sorting works 4 times faster. Although this can't be, because in the best case, shell sorting is performed in time n(log n)^2, while merge sorting is performed in nlogn time, which is faster than shell sorting. What could be the problem? I tried it on different PCs, but shell sorting is still faster.
UPD: For arrays filled randomly, it works as it should, but for already sorted ones, shell sorting works twice as fast.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <time.h>
#define DIFF 3276
double wtime(void);
void randArray(int* array, int size);
void shellSort(int a[], int size);
void merge(int arr[], int l, int m, int r);
void mergeSort(int arr[], int l, int r);
int main(void)
{
FILE* file1;
FILE* file2;
int* array = NULL;
unsigned seed = time(NULL);
if (!(file1 = fopen("shell.txt", "w"))) {
return 1;
}
for (int step = DIFF; step <= 32760; step += DIFF) {
srand(seed);
array = (int*)malloc(step * sizeof(int));
double start, end;
randArray(array, step);
start = wtime();
shellSort(array, step);
end = wtime();
free(array);
fprintf(file1, "%d\t%lf\n", step, end - start);
}
fclose(file1);
if (!(file2 = fopen("merge.txt", "w"))) {
return 1;
}
for (int step = DIFF; step <= 32760; step += DIFF) {
srand(seed);
array = (int*)malloc(step * sizeof(int));
double start, end;
randArray(array, step);
start = wtime();
mergeSort(array, 0, step - 1);
end = wtime();
free(array);
fprintf(file2, "%d\t%lf\n", step, end - start);
}
fclose(file2);
}
void randArray(int* array, int size)
{
for (int i = 0; i < size; i++) {
array[i] = i;
}
}
double wtime(void)
{
struct timeval t;
gettimeofday(&t, NULL);
return (double)t.tv_sec + (double)t.tv_usec * 1E-6;
}
void shellSort(int a[], int size)
{
int i, j;
int s = size / 2;
while (s > 0) {
for (i = s; i < size; i++) {
int temp = a[i];
for (j = i - s; (j >= 0) && (a[j] > temp); j -= s)
a[j + s] = a[j];
a[j + s] = temp;
}
s /= 2;
}
}
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];
for (j = 0; j < n2; j++)
R[j] = arr[m + 1 + j];
i = 0;
j = 0;
k = l;
while (i < n1 && j < n2) {
if (L[i] <= R[j]) {
arr[k] = L[i];
i++;
} else {
arr[k] = R[j];
j++;
}
k++;
}
while (i < n1) {
arr[k] = L[i];
i++;
k++;
}
while (j < n2) {
arr[k] = R[j];
j++;
k++;
}
}
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);
}
}
Your shell sort works in-place and for a sorted array it never swaps a single element. So it only has the cost of the compares and the branch predictor will predict the compare perfectly every time.
Your merge sort on the other hand copies the data to temp arrays and back in every step. That's 2 * log(n) copies of the whole array. The extra memory needed might also exceed the L1 cache of your CPU for the larger test runs making this magnitudes worse. You can cut that in half by alternating between 2 arrays, well almost log(n) + 1 copies worst case. Branch prediction for the sorted case is perfect too, it's just the copies that cost you.
So I try to do the Heap Sort in C for a row of an 2d array
So basically I find the smallest sum of all the rows from the array and I try to sort the elements of that row, for that I'm trying to store the index of the smallest row with a pointer but when I use pointer the programm it's not returning the index but the adress
//funcion to find the smallest row sum
void min_rand(int(*a)[50], int n, int m, int *mi)
{
int min_row = 0;
int i, j;
for (j = 0; j < m; j++)
min_row += a[0][j];
for (i = 0; i < n; i++) {
int sum_row = 0;
for (j = 0; j < m; j++)
sum_row += a[i][j];
if (sum_row < min_row) {
min_row = sum_row;
*mi = i;
}
}
}
void swap(int *a, int *b)
{
int temp = *a;
*a = *b;
*b = temp;
}
void heapify_c(int(*a)[50], int n, int i, int mi)
{
int largest = i;
int l = 2 *i + 1;
int r = 2 *i + 2;
if (l < n && a[mi][l] > a[mi][largest])
largest = l;
if (r < n && a[mi][r] > a[mi][largest])
largest = r;
if (largest != i) {
swap(&a[mi][i], &a[mi][largest]);
heapify_c(a, n, largest, mi);
}
}
void heapSort_c(int(*a)[50], int n, int mi)
{
for (int i = n / 2 - 1; i >= 0; i--)
heapify_c(a, n, i, mi);
for (int i = n - 1; i > 0; i--) {
swap(&a[mi][0], &a[mi][i]);
heapify_c(a, i, 0, mi);
}
}
int main()
{
int a[50][50];
int n, m, mi;
min_rand(a, n, m, &mi);
heapSort_c(a, n, mi);
return 0;
}
I don't print the sorted elements in the e.g. above but I just want to know if I'm doing something so terrebly wrong cause I did this before with counting sort and it worked without any problems
I'm new to programming,I'm trying to implement a merge sort function into my program, but it's not working correctly. I went over and over the code but I can't find the problem.
If for example the user input for a 6 element array is : 3 2 4 1 6 7
The output is: 1 3 2 4 32708 32708
Can someone help me? Also, if anyone have any advice for improving my coding style would be much appreciated.Thanks.
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int *a, n;
a = malloc(100 * sizeof(int)); // dynamically allocating memory for original array
if (a == NULL)
return 1;
printf("Enter n of elements in the array:");
scanf("%i", &n); // n of elements the in array
printf("Enter elements:\n");
for (int i = 0; i < n; i++) {
scanf("%i", &a[i]); // prompt user for input elements
}
int f, l, m, n1, n2; // declaring variables
f = 0; // first element
l = n - 1; // last element
m = (f + l) / 2; // mid point
n1 = m + 1 - f; // n elements l1
n2 = l - m; // n elements l2
int l1[n1]; // temp array 1
int l2[n2]; // temp array2
for (int i = 0; i < n1; i++) {
l1[i] = a[i]; // copy elements into temp l1
}
for (int j = 0; j < n2; j++) {
l2[j] = a[m + 1 + j]; // copy elements into temp l2
}
int i, j, k; // variable for arrays index
i = 0;
j = 0;
k = 0;
//sorting and copying elements in original array
while (i < n1 && j < n2) {
if (l1[i] <= l2[j]) { // if element l1 smaller or equal to l2 element
a[k] = l1[i]; // copy element l1 into original array
i++; // increment l1
} else { // if element l1 bigger than l2
a[k] = l2[j]; // copy element l2 into original array
j++; // increment l2
}
k++; // increment original array
}
// copy remaining elements (if any)
while (i < n1) {
a[k] = l1[i];
i++;
k++;
}
while (j < n2) {
a[k] = l2[i];
j++;
k++;
}
printf("Your sorted array:\n");
for (int d = 0; d < n; d++) {
printf("%i ", a[d]); // print sorted array
}
printf("\n");
free(a); // freeing original array
}
You need to merge recursively. You wrote only the merge part and not the recursive sort function.
More info: https://www.geeksforgeeks.org/merge-sort/
#include <stdio.h>
#include <stdlib.h>
void merge(int arr[], int l, int m, int r)
{
int i, j, k;
int n1 = m - l + 1;
int n2 = r - m;
/* create temp arrays */
int L[n1], R[n2];
/* Copy data to temp arrays L[] and R[] */
for (i = 0; i < n1; i++)
L[i] = arr[l + i];
for (j = 0; j < n2; j++)
R[j] = arr[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]) {
arr[k] = L[i];
i++;
} else {
arr[k] = R[j];
j++;
}
k++;
}
/* Copy the remaining elements of L[], if there are any */
while (i < n1) {
arr[k] = L[i];
i++;
k++;
}
/* Copy the remaining elements of R[], if there are any */
while (j < n2) {
arr[k] = R[j];
j++;
k++;
}
}
void mergeSort(int arr[], int l, int r)
{
if (l < r) {
// Same as (l+r)/2, but avoids overflow for
// large l and h
int m = l + (r - l) / 2;
// Sort first and second halves
mergeSort(arr, l, m);
mergeSort(arr, m + 1, r);
merge(arr, l, m, r);
}
}
int main(void)
{
int *a, n;
printf("Enter n of elements in the array:");
scanf("%i", &n); //n of elements the in array
a = malloc(n * sizeof(int)); //dynamically allocating memory for original array
if (a == NULL)
return 1;
printf("Enter elements:\n");
for (int i = 0; i < n; i++) {
scanf("%i", &a[i]); //prompt user for input elements
}
mergeSort(a, 0, n - 1);
printf("Your sorted array:\n");
for (int d = 0; d < n; d++) {
printf("%i ", a[d]); //print sorted array
}
printf("\n");
free(a); //freeing original array
return 0;
}
I have to test Mergesort with different sizes of data. The problem I encounter is that if the array of ints is around the size of 5000000 my code is crashing but without giving an error. I calculated the amount of space the array would take and if I'm not wrong this would be about 0,02 GB and my RAM is 8GB. I also searched if there is a max size for an array and didnt find anything useful. So where is the problem?
/* C program for Merge Sort */
#include<stdlib.h>
#include<stdio.h>
#include <time.h>
#define MAX 2000000
int arr[MAX];
// Merges two subarrays of arr[].
// First subarray is arr[l..m]
// Second subarray is arr[m+1..r]
void merge(int l, int m, int r)
{
int i, j, k;
int n1 = m - l + 1;
int n2 = r - m;
/* create temp arrays */
int L[n1], R[n2];
/* Copy data to temp arrays L[] and R[] */
for (i = 0; i < n1; i++)
L[i] = arr[l + i];
for (j = 0; j < n2; j++)
R[j] = arr[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])
{
arr[k] = L[i];
i++;
}
else
{
arr[k] = R[j];
j++;
}
k++;
}
/* Copy the remaining elements of L[], if there
are any */
while (i < n1)
{
arr[k] = L[i];
i++;
k++;
}
/* Copy the remaining elements of R[], if there
are any */
while (j < n2)
{
arr[k] = R[j];
j++;
k++;
}
}
/* l is for left index and r is right index of the
sub-array of arr to be sorted */
void mergeSort(int l, int r)
{
if (l < r)
{
// Same as (l+r)/2, but avoids overflow for
// large l and h
int m = l+(r-l)/2;
// Sort first and second halves
mergeSort(l, m);
mergeSort(m+1, r);
merge(l, m, r);
}
}
/* UTILITY FUNCTIONS */
/* Function to print an array */
void printArray()
{
int i;
for (i=0; i < MAX; i++)
printf("%d ", arr[i]);
printf("\n");
}
/* Driver program to test above functions */
int main()
{
srand(time(NULL));
for (int var = 0; var < MAX; ++var) {
arr[var] = rand() % 100;
}
clock_t t1, t2;
//printf("Given array is \n");
// printArray();
t1 = clock();
mergeSort(0, MAX - 1);
t2 = clock();
printf("\nSorted array is \n");
printArray();
float timetaken = t2 - t1;
timetaken /= CLOCKS_PER_SEC;
printf("Time spend: %f\n", timetaken);
return 0;
}
in
void merge(int l, int m, int r)
{
int i, j, k;
int n1 = m - l + 1;
int n2 = r - m;
/* create temp arrays */
int L[n1], R[n2];
...
Probably L and R are too large to be placed in the stack, the size of the stack is limited, do ulimit-a to see the limit.
If this is the reason you will have to allocate them in the heap (malloc), and don't forget after to free them ;-)
When you need a big array whose size if a constant (this is not the case here) and the function using it is not directly nor indirectly recursive, you can use a static var, I mean for example : void foo() { ... static int v[4096]; ... } rather than void foo() { ... int v[4096]; ... }
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
}