#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/time.h>
#include <time.h>
void DISPLAY(int*, int);
int* MERGE(int*, int, int* , int, int* , int );
int* MERGESORT(int* , int );
int main()
{
int* array = NULL;
array = (int*) malloc(7 * sizeof(int) );
array[0] = 10;
array[1] = 9;
array[2] = 8;
array[3] = 57;
array[4] = 6;
array[5] = 5;
array[6] = 24;
printf("\nOriginal array: \n");
DISPLAY(array, 7);
array = MERGESORT(array, 7);
printf("\n\nResulting array: \n");
DISPLAY(array, 7);
}
void DISPLAY(int* array, int size)
{
int i;
for(i = 0; i < size; i++){
printf("%d ", array[i]);
}
}
int* MERGESORT(int *array, int size) {
if(size < 2)
return array;
int mid = size / 2;
int rightsize = size-mid;
int* L = (int*) malloc(mid * sizeof(int));
int* R = (int*) malloc((size-mid) * sizeof(int));
int i;
for(i = 0; i < mid; i++)
L[i] = array[i];
for(i = mid; i < size; i++)
R[i-mid] = array[i];
L = MERGESORT(L, mid);
R = MERGESORT(R, size-mid);
array = MERGE(array, size, L, mid, R, rightsize);
free(L);
free(R);
return array;
}
int* MERGE(int *array, int size, int *L, int leftsize,int *R, int rightsize) {
int i, j, k;
i = 0;
j = 0;
k = 0;
while(i < leftsize && j < rightsize)
{
if(L[i] < R[j])
{
array[k] = L[i];
i++;
}
else{
array[k] = R[j];
j++;
}
k++;
}
while(i < leftsize)
{
array[k] = L[i];
i++;
k++;
}
while(j < rightsize)
{
array[k] = L[j];
j++;
k++;
}
printf("\nUpdated array: \n");
DISPLAY(array, size);
return array;
}
Hello, I have a problem when I try to perform merge sorting in an array. Some items in the array are printing weird. Every time the arrays get updated, the value gets printed out, but it doesn't work at specific inputs.
When I input small numbers (like 1-2 digits), then the array gets sorted normally.
Sample run of program sorting incorrectly:
https://i.stack.imgur.com/OLg0b.png
while(j < rightsize)
{
array[k] = L[j];
j++;
k++;
}
should be
while(j < rightsize)
{
array[k] = R[j];
j++;
k++;
}
Umm, sorry for wasting time on such a simple mistake.
Consider.
int* R = (int*) malloc((size-mid) * sizeof(int));
(which ought to be written int *R = malloc((size - mid) * sizeof *R);)
What is the highest valid index in that array? Trying to read from (or write to) R[n] for n > size - mid - 1 invokes undefined behavior.
Related
I'm trying to write an iterative function that computes all the permutations of an array of numbers given in input.
Here is the code I've written so far.
void permute(int *a, int size){
int j=0, i, h=0, m;
bool flag=true;
int f = factorial(size);
int *arr, *res;
int counter=0;
arr = malloc(f*sizeof(int));
for(i=0; i<f; i++)
arr[i] = 0;
while (j < f) {
if(arr[j]<j)
{
if(j%2 == 0)
{
swap(a[0],a[j]);
} else {
swap(a[arr[j]], a[j]);
}
arr[j]++;
j=0;
} else{
arr[j] = 0;
j++;
}
printf("%d\n",a[j] );
}
}
The code doesn't compute well all the permutations and goes into a long loop. Can someone help me, please? Thanks to everyone.
Your code is close but includes some problems. For instance, the while loop
while (j < f) will assign j to a value out of bound of the array a.
Instead would you please try:
#include <stdio.h>
#include <stdlib.h>
int factorial(int x)
{
int i;
int y = 1;
for (i = 1; i <= x; i++) {
y *= i;
}
return y;
}
void swap(int *x, int *y)
{
int temp;
temp = *x;
*x = *y;
*y = temp;
}
void permute(int *a, int size)
{
int i, j = 0;
int f = factorial(size);
int *arr;
arr = calloc(f, sizeof(int)); // the members are initialized to 0
// print the original array
for (i = 0; i < size; i++) {
printf("%d%s", a[i], i == size - 1 ? "\n" : " ");
}
while (j < size) {
if (arr[j] < j) {
if (j % 2 == 0) {
swap(a + 0, a + j);
} else {
swap(a + arr[j], a + j);
}
// print the rearranged array
for (i = 0; i < size; i++) {
printf("%d%s", a[i], i == size - 1 ? "\n" : " ");
}
arr[j]++;
j = 0;
} else {
arr[j] = 0;
j++;
}
}
free(arr);
}
int main()
{
int a[] = {1, 2, 3}; // example
permute(a, sizeof a / sizeof a[0]); // the 2nd argument is the array length
return 0;
}
Output of the example:
1 2 3
2 1 3
3 1 2
1 3 2
2 3 1
3 2 1
I am writing one of the merge sort variations. In my task I use two arrays: keys in arr array and values in brr array. Keys are integer numbers and values are strings. Merge function receives these two arrays, l, m and r as left, middle and right indexes.
void merge(int arr[], char** brr, int l, int m, int r)
I calculate the sizes of two new arrays, that I will need:
int size1 = m-l+1;
int size2 = r-m;
To merge arrays, I create two new arrays for keys and strings using malloc function:
int* left = malloc(size1*sizeof(int));
int* right = malloc(size2*sizeof(int));
char** lefts = malloc(size1*sizeof(char*));
char** rights = malloc(size2*sizeof(char*));
Then I copy values from the input arrays:
for(int i = 0; i < size1; i++){
left[i] = arr[l+i];
lefts[i] = brr[l+i];
}
And do sorting steps with new arrays.
i = j = 0;
k = l;
while(i < size1 && j < size2){
if(left[i] < right[j]){
brr[k] = lefts[i];
arr[k] = left[i];
i++;
}else{
brr[k] = rights[j];
arr[k] = right[j];
j++;
}
k++;
}
Then I add to brr arrays last items and after trying to free memory of rights array I get an error.
free(lefts);
lefts = NULL;
free(rights);
rights = NULL;
Note: there is no error when trying to free memory of lefts array, only rights. I tried to swap free(lefts) and free(rights), but result is the same.
Full function code:
void merge(int arr[], char** brr, int l, int m, int r){
int size1 = m-l+1;
int size2 = r-m;
int* left = malloc(size1*sizeof(int));
int* right = malloc(size2*sizeof(int));
char** lefts = malloc(size1*sizeof(char*));
char** rights = malloc(size2*sizeof(char*));
for(int i = 0; i < size1; i++){
left[i] = arr[l+i];
lefts[i] = brr[l+i];
}
for(int i = 0; i < size2; i++){
right[i] = arr[m+1+i];
rights[i] = brr[m+1+i];
}
int i, j, k;
i = j = 0;
k = l;
while(i < size1 && j < size2){
if(left[i] < right[j]){
brr[k] = lefts[i];
arr[k] = left[i];
i++;
}else{
brr[k] = rights[j];
arr[k] = right[j];
j++;
}
k++;
}
while(i < size1){
brr[k] = lefts[i];
arr[k] = left[i];
k++;
i++;
}
while(j < size2){
brr[k] = rights[j];
arr[k] = right[j];
k++;
j++;
}
free(left);
left = NULL;
free(right);
right = NULL;
free(lefts);
lefts = NULL;
free(rights);
rights = NULL;
}
MergeSort function:
void mergeSort(int arr[], char** brr, int l, int r){
if(l < r){
int m = l+(r-l)/2;
mergeSort(arr, brr, l, m);
mergeSort(arr, brr, m+1, r);
merge(arr, brr, l, m, r);
}
}
Main:
int main(){
const int maxStrings = 14;
const int maxStringSize = 70;
int n;
scanf("%d", &n);
getchar();
int *Keys = malloc(n*sizeof(int));
for(int i = 0; i < maxStrings; i++) Keys[i] = i;
char **Strings = malloc(n*sizeof(char*));
char *temp;
for(int i = 0; i < n; i++){
getStr(&temp, maxStringSize);
Strings[i] = temp;
}
mergeSort(Keys, Strings, 0, n-1);
}
getStr:
void getStr(char **a, int n){
*a = malloc(n*sizeof(char));
char c;
int i = 0;
while( (c = getchar()) != '\n' && i < n-1){
if(c == EOF){
(*a)[i] = '\0';
return;
}
(*a)[i++] = c;
}
(*a)[i] = '\0';
}
The error is typically a sign of overwriting some memory that doesn't belong to you. Typically you have destroyed the "mallocs book-keeping data" for the variable you are freeing.
So look for illegal memory writes. How about this code?
int *Keys = malloc(n*sizeof(int));
for(int i = 0; i < maxStrings; i++) Keys[i] = i;
You malloc only n elements but still you write maxStrings elements. So if n is less than maxStrings you have a write out side allocated memory.
In your main, this: for(int i = 0; i < maxStrings; i++) should be up to n, instead of up to maxStrings no?
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
}
#include <stdio.h>
#include <stdlib.h>
void printingArr(int** arr, int rows);
void sortingEachOneOfThem(int** pArr, int rows);
void sortingTheWholeArray(int** pArr, int rows);
void bubbleSort(int* arr);
void freeArray(int **a, int m);
int main(void)
{
int** pArr = 0;
int numOfRows = 0;
int sizes = 0;
printf("Enter number of rows: ");
scanf("%d", &numOfRows);
pArr = (int**) malloc(sizeof(int*) * numOfRows);
if (pArr == NULL)
{
printf("Unsuccessful malloc!\n");
return 1;
}
for (int i = 0; i < numOfRows; i++)
{
printf("Enter array length for row %d: ",i);
scanf("%d", &sizes);
pArr[i] = (int*) malloc(sizeof(int) * sizes + 1);
if (pArr[i] == NULL)
{
printf("Unsuccessful malloc!\n");
return 1;
}
pArr[i][0] = sizes;
for (int k = 1; k < sizes + 1; k++)
{
printf("Enter value for array: ");
scanf("%d", &pArr[i][k]);
}
}
printingArr(pArr, numOfRows);
sortingEachOneOfThem(pArr, numOfRows);
printingArr(pArr, numOfRows);
sortingTheWholeArray(pArr, numOfRows);
printingArr(pArr, numOfRows);
for (int i = 0; i < numOfRows; i++)
{
if (pArr[i] != NULL)
{
free(*(pArr + i));
}
}
//free(pArr);
system("pause");
return 0;
}
/*
this amazing, wonderfull piece of program prints the array given
input: int** arr, int rows
output: none
*/
void printingArr(int** arr, int rows)
{
int i = 0;
int k = 0;
for (i = 0; i < rows; i++)
{
for (k = 0; k <= arr[i][0]; k++)
{
printf("%d ", arr[i][k]);
}
printf("\n");
}
printf("\n");
}
/*
This beautiful function sorts the whole array, but its length of rows like a pyramid
input: int** arr, int rows
output: none
*/
void sortingTheWholeArray(int** pArr, int rows)
{
int* temp = 0;
int i = 0, k = 0;
for (i = 0; i < rows - 1; i++)
{
for (k = 0; k < rows - 1; k++)
{
if (pArr[k][0] > pArr[k + 1][0])
{
temp = pArr[k];
pArr[k] = pArr[k + 1];
pArr[k + 1] = temp;
}
}
}
}
/*
This little small function sorts every row of the array of arrays given to it
input: int** arr, int rows
output: none
*/
void sortingEachOneOfThem(int** pArr, int rows)
{
int i = 0;
for (i = 0; i < rows; i++)
{
bubbleSort(pArr[i]);
}
}
/*
This little piece of a code is a bubble sort, sorts the array given to it :)
input: int* arr, int rows
output: none
*/
void bubbleSort(int* arr)
{
int i = 1, k = 0;
for (i = 1; i < arr[0] - 1; i++)
{
for (k = 1; k <= arr[0] - i; k++)
{
if (arr[k] > arr[k + 1])
{
arr[k] += arr[k + 1];
arr[k + 1] = arr[k] - arr[k + 1];
arr[k] -= arr[k + 1];
}
}
}
}
the free at the end crashes my code, showing this error:
https://i.stack.imgur.com/nqxBG.png
the same usage of the function free() on another code worked good, but not here. I have tried running through it in step by step mode, it crashes at the first free. Dr. memory shows this: https://i.stack.imgur.com/rSZJr.png
another link: https:// i.stack. imgur.com/ZX2Ne.png (paste it without the spaces in the middle, Can't post more than 2 links)
what can I do?
This:
pArr[i] = (int*) malloc(sizeof(int) * sizes + 1);
under-allocates. Adding a single byte to the size of an array of int makes little sense. You probably meant:
pArr[i] = malloc((sizes + 1) * sizeof *pArri[i]);
Don't cast the return value of malloc(), and use sizeof on the left-hand side.
Basically this is a C code for Oil Well challenge from hackerrank website (https://www.hackerrank.com/challenges/oil-well). I am getting segmentation fault or abort called when I submit this code.(It is working sometime in my system compiler).
Can someone tell me how to rectify this problem?. Thanks in advance.
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <limits.h>
#include <stdbool.h>
int *min, c, r, q = 0;
void findmin()
{
int i, minimum = min[0];
for (i = 0; i < q; i++)
{
if (min[i] > minimum)
minimum = min[i];
}
printf("%d", minimum);
}
void calculate(int a[], int r)
{
int sum = 0;
int i;
int *x, *y;
x = (int *) malloc(sizeof(int) * 3);
y = (int *) malloc(sizeof(int) * 3);
for (i = 0; i <= r; i++)
{
x[i] = a[i] % c;
y[i] = a[i] / c;
}
for (i = 1; i <= r; i++)
{
if ((x[i] - x[i - 1]) > (y[i] - y[i - 1]))
sum = sum + (x[i] - x[i - 1]);
else
sum = sum + (y[i] - y[i - 1]);
}
min[q] = sum;
q++;
free(x);
free(y);
}
void swap(int *x, int *y)
{
int temp;
temp = *x;
*x = *y;
*y = temp;
}
void permute(int a[], int l, int r)
{
int i;
if (l == r)
{
for (i = 0; i <= r; i++)
calculate(a, r);
}
else
{
for (i = l; i <= r; i++)
{
swap((a + l), (a + i));
permute(a, l + 1, r);
swap((a + l), (a + i));
}
}
}
int main(void)
{
int i, j, k = 0;
scanf("%d%d", &r, &c);
int *arr;
arr = (int *) malloc(sizeof(int) * r * c);
int **x = (int **) malloc(r * sizeof(int *));
for (i = 0; i < r; i++)
x[i] = (int *) malloc(c * sizeof(int));
for (i = 0; i < r; i++)
for (j = 0; j < c; j++)
scanf("%d", &x[i][j]);
for (i = 0; i < r; i++)
{
for (j = 0; j < c; j++)
{
if (x[i][j] == 1)
{
arr[k] = c * i + j;
k++;
}
}
}
/*printf("Content of arr array is:\n");
for(i=0;i<k;i++)
printf("%d \n",arr[i]);
*/
min = (int *) malloc(sizeof(int) * r * c);
permute(arr, 0, k - 1);
findmin();
free(arr);
free(x);
free(min);
}
Updated code(With all the suggestions and answers taken into account )
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <limits.h>
#include <stdbool.h>
int *min,c,r,q=0;
void findmin()
{
int i,minimum=min[0];
/*printf("\nmin array is \n");
for(i=0;i<q;i++)
{
printf("%d ",min[i]);
}*/
for(i=0;i<q;i++)
{
if(min[i]<minimum)
minimum=min[i];
}
printf("%d",minimum);
}
void calculate(int a[],int r)
{
int sum=0;
int i;
int *x,*y;
x = (int *)malloc(sizeof(int)*r+1);
y = (int *)malloc(sizeof(int)*r+1);
for(i=0;i<=r;i++)
{
x[i]=a[i]%c;
y[i]=a[i]/c;
}
for(i=1;i<=r;i++)
{
if(abs(x[i]-x[i-1])>abs(y[i]-y[i-1]))
sum=sum+abs(x[i]-x[i-1]);
else
sum=sum+abs(y[i]-y[i-1]);
}
min[q]=sum;
q++;
free(x);
free(y);
//printf("I am here also");
}
void swap(int *x,int *y)
{
int temp;
temp=*x;
*x=*y;
*y=temp;
}
void permute(int a[],int l,int r)
{
int i;
if(l==r)
{
for(i=0;i<=r;i++)
//printf("%d ",a[i]);
calculate(a,r);
//printf("\n");
}
else
{
for(i=l;i<=r;i++)
{
swap((a+l),(a+i));
permute(a,l+1,r);
swap((a+l),(a+i));
}
}
}
int main(){
int i,j,k=0;
scanf("%d%d",&r,&c);
int *arr;
arr = (int *)malloc(sizeof(int)*r*c);
int **x = (int **)malloc(r * sizeof(int *));
for (i=0; i<r; i++)
x[i] = (int *)malloc(c * sizeof(int));
for(i=0;i<r;i++)
for(j=0;j<c;j++)
scanf("%d",&x[i][j]);
/*for(i=0;i<r;i++)
{
for(j=0;j<c;j++)
printf("%d ",x[i][j]);
printf("\n");
}*/
for(i=0;i<r;i++)
{
for(j=0;j<c;j++)
{
if(x[i][j]==1)
{
arr[k]=c*i+j;
k++;
}
}
}
//printf("Content of arr array is:\n");
//for(i=0;i<k;i++)
//printf("%d \n",arr[i]);
//printf("\nCalling permutation\n");
min = (int *)malloc(sizeof(int)*r*c);
permute(arr,0,k-1);
//printf("\nFinding min call\n");
findmin();
free(arr);
for (i = 0; i < r; i++)
{
free(x[i]);
}
free(x);
free(min);
return 0;
}
Here do *(r+1) rather than *3
x = (int *)malloc(sizeof(int)*3);
y = (int *)malloc(sizeof(int)*3);
Change min[i] > minimum to min[i] < minimum
free all the memory you've allocated i.e. from x[0] to x[r] and y[0] to y[r].
Other than this you're probably all good.
You are allocating (r * sizeof (int)) + 1 bytes,
x = (int *)malloc(sizeof(int)*r+1);
y = (int *)malloc(sizeof(int)*r+1);
but your loop accesses r+1 int objects:
for(i=0;i<=r;i++)
{
x[i]=a[i]%c;
y[i]=a[i]/c;
}
Correct the behaviour based on whatever your intent is - I suspect you want to allocate (r + 1) * sizeof (int) bytes.