I'm having trouble tracking down a "conditional jump or move depends on uninitialised value(s)" valgrind error in some mergesort code I wrote. The code sorts things properly, but I know there's a memory leak from a variable not being initialized. Valgrind tells me it's in the m_sort portion of my code, but I'm not sure what's not being initialized.
void merge(int *C, int *A, int n, int *B, int m) {
int i, j, k;
for (i=0,j=0,k=0; k<(n+m); k++) {
if (i==n) {
C[k] = B[j];
j++;
}
else if (j==m) {
C[k] = A[i];
i++;
}
else {
if (A[i] < B[j]) {
C[k] = A[i];
i++;
}
else {
C[k] = B[j];
j++;
}
}
}
}
void m_sort(int *A, int *B, int left, int right) {
int mid;
if (right >left) {
mid =((right + left)/2);
m_sort(B, A, left, mid);
m_sort(B, A, mid+1, right);
merge(A+left, B+left, mid-left+1, B+mid+1, right-mid);
}
}
void merge_sort(int *a, int left, int right)
{
int * T = NULL;
int i;
T = (int*)malloc((right+1)*sizeof(int));
for (i=0; i<right; i++)
{
T[i] = a[i];
}
m_sort(a,T,left,right);
free(T);
}
Related
My code here gets terminated after printing the unsorted array and also gives runtime error on ideone , i am unable to find the error in it . code works fine until the first mergesort in function but gets terminated afterwards without executing merge function . I have tried changing array size but nothing has worked so far . Any help would be appreciated.
#include<stdio.h>
#include<math.h>
void Merge(int arr[],int,int,int,int);
void printArray(int *arr,int n)
{
for (int i = 0; i < n; i++)
{
printf("%d",arr[i]);
printf(" ");
}
printf("\n");
}
void MergeSort(int arr[],int low,int high)
{
int mid;
if(low<high)
{
mid = ceil((low+high)/2);
MergeSort(arr,low,mid-1);
MergeSort(arr,mid,high);
Merge(arr,low,mid-1,mid,high);
}
}
void Merge(int arr[],int low,int mid1,int mid2, int high)
{
int i,c,j;
c = low;
i = low;
j = mid2;
int Temp[high-low+1];
while(i <= mid1 && j<= high)
{
if(arr[i]<arr[j])
{
Temp[c] = arr[i];
i++;
c++;
}
else
{
Temp[c] = arr[j];
j++;
c++;
}
}
while(i<=mid1)
{
Temp[c] = arr[i];
i++;
c++;
}
while(j<=high)
{
Temp[c] = arr[j];
j++;
c++;
}
for(int k=0;k<=high;k++)
{
arr[k] = Temp[k];
}
}
int main(void)
{
int arr[] = {3,5,2,13,12,3,2,13,45};
int n = sizeof(arr)/sizeof(arr[0]);
printf("unsorted array: \n");
printArray(arr,n);
MergeSort(arr,0,n-1);
printf("sorted array: \n");
printArray(arr,n);
return 0;
}
There are several issues:
ceil is not useful as / will perform an integer division and so has already rounded down
Related to this, you should not use mid-1 and mid as arguments in the next recursive calls, but mid and mid+1. The same should be done with the arguments to Merge.
The way you access Temp is wrong. You allocate entries from 0 to high-low, but start your access with a value of c that is low. You should instead start at index 0.
In the very last loop k runs from 0 to high, but that are too many iterations. It should start from low, and then the index access to Temp should again be adapted by using k-low as index.
Here is the corrected code:
void MergeSort(int arr[],int low,int high)
{
int mid;
if(low<high)
{
mid = (low+high)/2; // <--
MergeSort(arr,low,mid); // <--
MergeSort(arr,mid+1,high); // <--
Merge(arr,low,mid,mid+1,high); // <--
}
}
void Merge(int arr[],int low,int mid1,int mid2, int high)
{
int i,c,j;
c = 0; // <--
i = low;
j = mid2;
int Temp[high-low+1];
while(i <= mid1 && j<= high)
{
if(arr[i]<arr[j])
{
Temp[c] = arr[i];
i++;
c++;
}
else
{
Temp[c] = arr[j];
j++;
c++;
}
}
while(i<=mid1)
{
Temp[c] = arr[i];
i++;
c++;
}
while(j<=high)
{
Temp[c] = arr[j];
j++;
c++;
}
for(int k=low;k<=high;k++) // <--
{
arr[k] = Temp[k-low]; // <--
}
}
Important note: I debugged the code for you, but this is something you can do yourself. Inspect the variables as you step through the code with a debugger, and spot where things are unexpected. It takes some time, but it is a skill a coder needs to learn.
edit: added main function
int main(int argc, char *argv[]) {
int arr[] = {3, 2, 1};
int n = sizeof(arr)/sizeof(arr[0]);
quicksort(arr, 0, n-1);
for (int i=0; i<n; i++) {
printf("%3d", arr[i]);
}
return 0;
}
void quicksort(int arr[], int left, int right) {
if (left<right) {
int pivot = partition(arr, left, right);
quicksort(arr, left, pivot-1);
quicksort(arr, pivot+1, right);
}
}
int partition(int arr[], int left, int right) {
/* left to i = smaller than pivot
i+1 = pivot
i+2 to right = bigger than pivot */
int pivot = right, i = left-1;
for (int j=left; j<right-1; j++) { // right-1 because the last num is the pivot
if (arr[j] < arr[pivot]) {
/* j scans the array for values that need to be swapped into the
right side of the partition */
i++;
swap(&arr[j], &arr[i]);
}
// swap pivot into the middle
swap(&arr[i+1], &arr[right]);
}
return i+1; // index of pivot
}
void swap(int *x, int *y)
{
int tmp = *x;
*x = *y;
*y = tmp;
}
I was following a tutorial and tried to translate pseudocode into C but I'm not sure what's wrong with my code
I'm using the input 3,2,1 but its outputting 2 1 3
int partition(int arr[], int left, int right) {
int pivot = right;
int i = left; // <-- set I to left not left -1
for (int j=left; j<right; j++) { // <-- no need for -1 (you already use less and not less or equal operator
if (arr[j] < arr[pivot]) {
swap(&arr[j], &arr[i]); // <-- do the swap first, then increment
i++;
}
}
// swap pivot into the middle
swap(&arr[i], &arr[right]); // <-- this needs to be outside the loop
return i; // <-- return I not I + 1
}
I was asked to create a function in C that gets an array of int's, its size and a character representing if the sort needs to be ascending or descending (0 for ascending, any other char if descending), and returns a pointers array. If the sort is ascending, the pointers will be sorted from minimum to maximum of the values in the int's array.
Like that
Everything works well until the pointers array is being returned to the main with a value of NULL. I mean, before the function ends and the array is being returned, there are values in the array (and they're also sorted well), but the moment the main gets the address from the function, it's null. Is anyone familiar with the problem?
Thank you!
#include <stdio.h>
#define SIZE 100
// Functions declaration
int** pointerSort(int* arr, unsigned int size, char ascend_flag);
void sortMerge (int** sortedArr, int left, int right, char ascend_flag);
void mergeSortAscend (int** arr, int left, int middle, int right);
void mergeSortDescend (int** arr, int left, int middle, int right);
void copyAddress(int** addressArray, int* arr, unsigned int size);
int main()
{
int** sortedArr;
int arr[5] = {8,1,7,2,4};
int size = 5;
sortedArr = pointerSort(arr, size, '1');
return 0;
}
// The pointerSort function gets an array, its size and a flag representing "sort by" (ascending, descending)
int** pointerSort(int* arr, unsigned int size, char ascend_flag)
{
// Variables declaration
int* sortedArr[size];
// Copying the addresses of each value in arr to an addresses array
copyAddress(sortedArr, arr, size);
// Sending the array of addresses, its start and end and the ascend_flag to the sortMerge function
sortMerge(sortedArr, 0, size - 1, ascend_flag);
return (sortedArr);
}
void sortMerge (int** sortedArr, int left, int right, char ascend_flag)
{
// Variables declaration
int middle = (left + right) / 2;
// Checking if there are more than one cell
if (left < right)
{
// Splitting the array into two
sortMerge(sortedArr, left, middle, ascend_flag);
sortMerge(sortedArr, middle + 1, right, ascend_flag);
// Checking if the sort requested is ascending or descending
if (ascend_flag != '0')
{
mergeSortAscend(sortedArr, left, middle, right);
}
else
{
mergeSortDescend(sortedArr, left, middle, right);
}
}
}
void mergeSortAscend (int** arr, int left, int middle, int right)
{
int l = left, m = middle + 1, r = right, i = left;
int* temp[SIZE];
while ((l <= middle) && (m <= right))
{
if (*(arr[l]) > *(arr[m]))
{
temp[i] = arr[m];
m++;
}
else
{
temp[i] = arr[l];
l++;
}
i++;
}
if (l <= middle)
{
while (l <= middle)
{
temp[i] = arr[l];
l++;
i++;
}
}
if (m <= right)
{
while (m <= right)
{
temp[i] = arr[m];
m++;
i++;
}
}
for (int k = left; k <= right; k++)
{
arr[k] = temp[k];
}
}
void copyAddress(int** addressArray, int* arr, unsigned int size)
{
int i;
for (i = 0; i < size; i++)
{
addressArray[i] = &(arr[i]);
}
}
void mergeSortDescend (int** arr, int left, int middle, int right)
{
int l = left, m = middle + 1, r = right, i = left;
int* temp[SIZE];
while ((l <= middle) && (m <= right))
{
if (*(arr[l]) <= *(arr[m]))
{
temp[i] = arr[m];
m++;
}
else
{
temp[i] = arr[l];
l++;
}
i++;
}
if (l <= middle)
{
while (l <= middle)
{
temp[i] = arr[l];
l++;
i++;
}
}
if (m <= right)
{
while (m <= right)
{
temp[i] = arr[m];
m++;
i++;
}
}
for (int k = left; k <= right; k++)
{
arr[k] = temp[k];
}
}
The int* sortedArr[size]; in int** pointerSort(int* arr, unsigned int size, char ascend_flag) becomes invalid as soon your function returns since it is an automatic variable allocated of the stack.
You need a permanent storage. For example allocate memory for sortedArr on the heap by the malloc function and return it.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 100
// Functions declaration
int** pointerSort(int* arr, unsigned int size, char ascend_flag);
void sortMerge (int** sortedArr, int left, int right, char ascend_flag);
void mergeSortAscend (int** arr, int left, int middle, int right);
void mergeSortDescend (int** arr, int left, int middle, int right);
void copyAddress(int** addressArray, int* arr, unsigned int size);
int main(void)
{
int** sortedArr;
int arr[5] = {8,1,7,2,4};
int size = 5;
int i =0;
sortedArr = pointerSort(arr, size, '1');
if(sortedArr) // memory was allocated
for(i=0; i<5; i++){
printf("%d ", *sortedArr[i]);
}
free(sortedArr);
return 0;
}
// The pointerSort function gets an array, its size and a flag representing "sort by" (ascending, descending)
int** pointerSort(int* arr, unsigned int size, char ascend_flag)
{
// Variables declaration
//int* sortedArr[size];
int ** sortedArr = malloc( sizeof(int *) * size);
if(sortedArr == NULL) return NULL; // no memory
// Copying the addresses of each value in arr to an addresses array
copyAddress(sortedArr, arr, size);
// Sending the array of addresses, its start and end and the ascend_flag to the sortMerge function
sortMerge(sortedArr, 0, size - 1, ascend_flag);
return (sortedArr);
}
void sortMerge (int** sortedArr, int left, int right, char ascend_flag)
{
// Variables declaration
int middle = (left + right) / 2;
// Checking if there are more than one cell
if (left < right)
{
// Splitting the array into two
sortMerge(sortedArr, left, middle, ascend_flag);
sortMerge(sortedArr, middle + 1, right, ascend_flag);
// Checking if the sort requested is ascending or descending
if (ascend_flag != '0')
{
mergeSortAscend(sortedArr, left, middle, right);
}
else
{
mergeSortDescend(sortedArr, left, middle, right);
}
}
}
void mergeSortAscend (int** arr, int left, int middle, int right)
{
int l = left, m = middle + 1, r = right, i = left;
int* temp[SIZE];
while ((l <= middle) && (m <= right))
{
if (*(arr[l]) > *(arr[m]))
{
temp[i] = arr[m];
m++;
}
else
{
temp[i] = arr[l];
l++;
}
i++;
}
if (l <= middle)
{
while (l <= middle)
{
temp[i] = arr[l];
l++;
i++;
}
}
if (m <= right)
{
while (m <= right)
{
temp[i] = arr[m];
m++;
i++;
}
}
for (int k = left; k <= right; k++)
{
arr[k] = temp[k];
}
}
void copyAddress(int** addressArray, int* arr, unsigned int size)
{
int i;
for (i = 0; i < size; i++)
{
addressArray[i] = &(arr[i]);
}
}
void mergeSortDescend (int** arr, int left, int middle, int right)
{
int l = left, m = middle + 1, r = right, i = left;
int* temp[SIZE];
while ((l <= middle) && (m <= right))
{
if (*(arr[l]) <= *(arr[m]))
{
temp[i] = arr[m];
m++;
}
else
{
temp[i] = arr[l];
l++;
}
i++;
}
if (l <= middle)
{
while (l <= middle)
{
temp[i] = arr[l];
l++;
i++;
}
}
if (m <= right)
{
while (m <= right)
{
temp[i] = arr[m];
m++;
i++;
}
}
for (int k = left; k <= right; k++)
{
arr[k] = temp[k];
}
}
Test:
1 2 4 7 8
I am a complete beginner to stackoverflow and this is my first post. Please forgive if this is not the correct place to post these kinds of queries. I have written code for the Quicksort algorithm, based on the algorithm given in the Algorithms course in Coursera(It is not for any assignments though).
Basically, there are two functions Quicksort which is called recursively and partition() function that returns the index of the pivot. I select the pivot as the first element of the array every time. I checked the partition() function and it works fine but the array is not sorted even after I call the Quicksort() function.
Any help is appreciated. Thanks.
#include <stdio.h>
void swap(int *p, int i, int j)
{
int temp = *(p+i);
*(p+i) = *(p+j);
*(p+j) = temp;
}
int partition(int *q, int l, int r)
{
int i = l+1, j;
int p = l;
int len = r-l +1;
for (j = l+1; j < len; j++)
{
/*printf("%d \n", j);*/
if ( *(q+j) < *(q+p) )
{
swap(q, i, j);
i += 1;
}
}
swap(q, l, i-1);
/*printf("%d", i-1);*/
return (i-1);
}
void quicksort(int *ptr, int low, int high)
{
if (low < high)
{
int p = partition(ptr, low, high);
printf("%d\n", p);
quicksort(ptr, low, p);
quicksort(ptr, p+1, high);
}
}
int main(){
int i;
int a[] = {3, 8, 2, 5, 1, 4, 7, 6};
int len = sizeof(a)/sizeof(a[0]);
for ( i = 0; i < len; ++i)
{
printf("%d ", a[i]);
}
printf("\n");
int *ptr = a;
quicksort(ptr, 0, len-1);
for (i = 0; i < sizeof(a)/sizeof(a[0]); ++i)
{
printf("%d ", a[i]);
}
printf("\n");
return 0;
}
2 corrections.
Small one: Change 3rd line inside if block in QuickSort function
from
quicksort(ptr, low, p);
to
quicksort(ptr, low, p-1);
This will improve performance.
Main error:
Your partition function is wrong. Specifically the loop where j runs from l+1 to r-l+1, because, r-l+1 can be less than l+1
I'll write the partition function for you if you want (post a comment if you face any problem with that) though I'd advice you to do it yourself.
EDIT:
A possible partition function:
int partition(int *q, int l, int r){
int i,j;
int p = *(q + l);
for(i = l + 1, j = r; ;){
while(*(q + i) <= p)
i++;
while(*(q + j) >= p)
j--;
if(i >= j)
break;
swap(q, i, j);
}
return i;
}
Changes noted in comments.
int partition(int *q, int l, int r)
{
int i = l+1, j;
int p = l;
/* fix: int len = r-l+1; is not used */
for (j = l+1; j <= r; j++) /* fix: j <= r */
{
if ( *(q+j) <= *(q+p) ) /* fix: <= */
{
swap(q, i, j);
i += 1;
}
}
swap(q, l, i-1);
return (i-1);
}
void quicksort(int *ptr, int low, int high)
{
if (low < high)
{
int p = partition(ptr, low, high);
quicksort(ptr, low, p-1); /* optimization: p-1 */
quicksort(ptr, p+1, high);
}
}
If interested, Hoare partition scheme is faster. If you switch to this, don't forget to change the two quicksort calls to quicksort(lo, p) and quicksort(p+1, hi) ). You might want to change the Hoare pivot to pivot = A[(lo+hi)/2], which will avoid worst case issue with sorted or reverse sorted array.
http://en.wikipedia.org/wiki/Quicksort#Hoare_partition_scheme
As an assignment I have to implement mergesort. I am getting segmentation faults as I am passing array as an argument. Everything appears to be correct. I am attaching the code.
arr is int arr[1000], I am passing it to mergesort as
mergesort(arr, 0, n);
Remaining code is as follows.
void merge(int a[], int l, int m, int r)
{
int temp[r -l];
int templ = l;
int tempm = m;
register int k;
for(k=0; k<(r-l); k++)
{
if((tempm >= r)||(templ < m)&&(a[templ] <= a[tempm]))
{ /*if number from left subarray is smaller*/
temp[k] = a[templ];
templ++;
}
else
{ /*number from right subarray is smaller*/
temp[k] = a[tempm];
tempm++;
}
}
for(k= l; k< r; k++)
{ /*copy results back to the array to be returned*/
a[k] = temp[k - l];
}
}
void mergesort(int ar[], int left, int right)
{
int mid;
if(left < right)
{
mid= (left + right)/2;
mergesort(&ar[0], left, mid - 1);
mergesort(&ar[0], mid, right);
merge(&ar[0], left, mid, right);
}
}
Once you have left == 0 and right == 1 in mergesort, you are going to have an infinite recursion:
void mergesort(int ar[], int left, int right) // IF LEFT IS 0 AND RIGHT IS 1 HERE...
{
int mid;
if(left < right) // ...THEN LEFT IS LESS THAN RIGHT AND...
{
mid= (left + right)/2;
mergesort(&ar[0], left, mid - 1);
mergesort(&ar[0], mid, right); // ...HERE WE HAVE A CALL THAT IS
// IDENTICAL TO THE ONE THAT GOT US HERE, INFINITE RECURSION