Related
I'm having issues with getting my mergeSort algorithm to work properly. The code is below, but I'll briefly summarize what I have tried and what I know is not wrong with the code.
The mergeSort function takes a pointer to an array and the array's size as arguments. If the size of the array is less than 2, it returns immediately. I'm sure that this works, because I debugged this part several times. It returns 8 times, which is what I expected it to do.
Next, a variable mid is created as an index to split the array by. I tested it, and I'm pretty confident that mid is correct across all recursions. Then, two arrays are created, the first containing the elements from the indexes 0...mid-1 and the second containing the elements from the indexes mid to n. Next, the sizes of each of these arrays are computed. I tested this too, and the sizes seem correct across all recursions as well. mergeSort is called on the left array and the right array, and then merge is called.
The actual merge function takes a pointer to the original array, a pointer to the left array, a pointer to the right array, and two integer values which are the sizes of each of the left and right arrays. Then, it compares the elements in L and R and copies the smaller of the two into A, in order.
My output, however, is [2] [4] [1] [6] [8] [5] [3] [7]
My expected output is: [1] [2] [3] [4] [5] [6] [7] [8]
I'm genuinely not sure why the code isn't working. There's probably something I'm overlooking, but I've been trying to solve it for an hour and figured I'd ask for help.
If you take the time to answer, or attempt to answer this question, thank you for your time.
My code is below:
#include <stdio.h>
#include <stdlib.h>
void mergeSort(int *, int);
void merge(int *, int *, int, int *, int);
void print(int *, int);
int main() {
int A[8] = { 2, 4, 1, 6, 8, 5, 3, 7 };
int arraySize = sizeof(A) / sizeof(A[0]);
mergeSort(A, arraySize);
print(A, arraySize);
}
void mergeSort(int *A, int n) {
if (n < 2) {
return;
}
int mid = n / 2;
int L[mid];
int R[n - mid];
for (int i = 0; i < mid; i++) {
L[i] = A[i];
}
for (int j = mid; j < n; j++) {
R[j - mid] = A[j + mid + 1];
}
int leftSize = sizeof(L) / sizeof(L[0]);
int rightSize = sizeof(R) / sizeof(R[0]);
mergeSort(L, leftSize);
mergeSort(R, rightSize);
merge(A, L, leftSize, R, rightSize);
}
void merge(int *A, int *L, int leftSize, int *R, int rightSize) {
int i, j, k;
while (i < leftSize && j < rightSize) {
if (L[i] < R[j]) {
A[k] = L[i];
k++;
i++;
} else {
A[k] = R[j];
k++;
j++;
}
}
}
void print(int *A, int n) {
for (int i = 0; i < n; i++) {
printf("[%d] ", A[i]);
}
printf("\n");
}
There are multiple problems:
the intialization loop for R is incorrect: you should copy A[j] instead of A[j + mid + 1]
the merge function should copy the remaining elements from the left or right arrays once the test i < leftSize && j < rightSize fails.
Here is a modified version:
#include <stdio.h>
#include <stdlib.h>
void mergeSort(int *, int);
void merge(int *, int *, int, int *, int);
void print(const int *, int);
int main() {
int A[8] = { 2, 4, 1, 6, 8, 5, 3, 7 };
int arraySize = sizeof(A) / sizeof(A[0]);
mergeSort(A, arraySize);
print(A, arraySize);
return 0;
}
void mergeSort(int *A, int n) {
if (n < 2) {
return;
}
int mid = n / 2;
int L[mid];
int R[n - mid];
for (int i = 0; i < mid; i++) {
L[i] = A[i];
}
for (int j = mid; j < n; j++) {
R[j - mid] = A[j];
}
int leftSize = sizeof(L) / sizeof(L[0]);
int rightSize = sizeof(R) / sizeof(R[0]);
mergeSort(L, leftSize);
mergeSort(R, rightSize);
merge(A, L, leftSize, R, rightSize);
}
void merge(int *A, int *L, int leftSize, int *R, int rightSize) {
int i, j, k;
while (i < leftSize && j < rightSize) {
if (L[i] <= R[j]) {
A[k++] = L[i++];
} else {
A[k++] = R[j++];
}
}
while (i < leftSize) {
A[k++] = L[i++];
}
while (j < rightSize) {
A[k++] = R[j++];
}
}
void print(const int *A, int n) {
for (int i = 0; i < n; i++) {
printf("[%d] ", A[i]);
}
printf("\n");
}
I tried to build a heap and finally print the elements in the form of an array.
Here it is the code (I know this doesn't really make sense but I just wanted to test my knowlwdge of heap and dynamic arrays):
#include <stdio.h>
#include <stdlib.h>
void heapiify(int *arr,int n, int i)
{
int largest=i;
int l=2*i+1; // left node
int r= 2*i+2; // right node
if(l<=n && *arr[l]>=*arr[i])
largest=l;
if (r <=n && *arr[r]<=*arr[i])
largest= r;
if(largest !=i)
{
int temp=*arr[i];
*arr[i]=*arr[largest];
*arr[largest]=temp;
}
heapify(*arr,n,largest);
}
void buildh(int *arr,int n,int r,int c)
{
int i;
for(i=n/2-1;i>=0;i--)
heapify(*arr,n,i);
output(*arr,r,c);
}
void output(int *arr,int r,int c)
{
int i,j;
for(i=0;i<r;i++)
{
for(j=0;j<c;j++)
{
printf("%d",*arr[i*c+j]);
}
printf("\n");
}
}
int main()
{
int i,j,r,c;
printf("enter the number of rows");
scanf("%d",&r);
printf("enter the number of columns");
scanf("%d",&c);
int n=r*c;
int *arr=malloc(n*sizeof(int));
for(i=0;i<r;i++)
{
for(j=0;j<c;j++)
scanf("%d",&arr[i*c+j]);
}
buildh(*arr,n,r,c);
}
I'm getting 9 errors which are all the same
invalid argument type of unary '*'( have int)
Your arr variable is of type pointer to int:
int *arr=malloc(n*sizeof(int));
So when you call buildh, which takes the same type, you have to pass it as-is:
buildh(arr,n,r,c);
Same for the other cases.
The problem is the dereference of arr, across your funtions in multiple places, and the passing of dereferenced *arr in your functions to int * parameters, you should pass arr, try:
//...
void heapify(int *arr, int n, int i)
{
int largest = i;
int l = 2 * i + 1; // left node
int r = 2 * i + 2; // right node
if (l <= n && arr[l] >= arr[i]) //here
largest = l;
if (r <= n && arr[r] <= arr[i]) //here
largest = r;
if (largest != i)
{
int temp = arr[i]; //here
arr[i] = arr[largest]; //here
arr[largest] = temp; //here
}
heapify(arr, n, largest); //here
}
void buildh(int *arr, int n, int r, int c)
{
int i;
for (i = n / 2 - 1; i >= 0; i--)
heapify(arr, n, i); //here
output(arr, r, c); //here
}
void output(int *arr, int r, int c)
{
int i, j;
for (i = 0; i < r; i++)
{
for (j = 0; j < c; j++)
{
printf("%d", arr[i * c + j]); //here
}
printf("\n");
}
}
int main()
{
//...
buildh(arr, n, r, c); //here
}
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;
}
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)
Here is my program it is compiling and running without syntax errors.How ever it does not sort the array.The problem lies in where I am passing the array in function
#include<stdio.h>
#include<string.h>
int partition (int *,int,int);
void quicksort (int *,int,int);
static int call=0;
int main()
{
int i,j,choice;
int length;
int a[]={81, 12, 90, 3, 49, 108, 47};
i=0;
length=sizeof(a)/sizeof(a[0]);
quicksort(a,0,length-1);
printf("the sorted array is\n");
for(i=0;i<length;i++)
printf (" %d ",a[i]);
}
int partition(int *num,int p,int r)
{
int x,j,i,temp,bak;
x=num[r];
i=p-1;
for(j=0;j<=r-1;j++)
{
if(num[j]<=x)
{
i=i+1;
temp=num[i];
num[i]=num[j];
num[j]=temp;
{
printf(" %d",num[bak]);
}
}
}
num[i+1]=num[r];
return i+1;
}
void quicksort (int *num,int p,int r)
{
int q;
if (p<r)
{
call++;
q=partition(num,p,r);
quicksort(num,p,q-1);
quicksort(num,q+1,r);
}
}
The above way of passing array in functions is that right that is what I want to know because that is giving problem in function partition.
Inside the function partition when swapping happens then I tried printing the array there itself (it is not sorted array but just to see upto what point things reached) then I saw that only 2 or 3 elements of array which I had passed are being printed and rest of the array is lost some where.So my doubt is array is not being passed properly.
To be able to see as what is the problem with array passing in a function I wrote a smaller program ka1.c
#include<stdio.h>
void pass(int *);
int main ()
{
int a[]={3,5,61,32,12};
pass(a);
}
void pass (int *num)
{
int i,j;
j=sizeof(num)/sizeof(num[0]);
for (i=0;i<j;i++)
printf(" %d",num[i]);
}
Now when I run the above code I get output just
3 5
I was expecting the complete array to be printed in output of ka1.c.
Where as if you notice rest of the array is not getting printed.Where did that go?
I have used the same logic in quicksort also hence I feel the error is same in both cases.
UPDATE1
After the comment below I checked the length of array recieved in quicsort.c paritition function via
sizeof(num)/sizeof(num[0]);
and found of original array
int a[]={81, 12, 90, 3, 49, 108, 47};
which is having length 7 here when I passed it in the function partition
the length is only 2.
The same is case with program ka1.c So why only length is 2 in both cases?
UPDATE2
As the suggestions given below now I have passed on the length also
#include<stdio.h>
#include<string.h>
int partition (int *,int,int,int);
void quicksort (int *,int,int,int);
static int call=0;
int main()
{
int i,j,choice;
int length;
int a[]={81, 12, 90, 3, 49, 108, 47};
i=0;
printf("the sorted array is\n");
length=sizeof(a)/sizeof(a[0]);
printf("length of array %d\n",length);
printf("quick sort called in main\n");
quicksort(a,0,length-1,length);
for(i=0;i<length;i++)
printf (" %d ",a[i]);
}
int partition(int *num,int p,int r,int june)
{
int x,j,i,temp,bak,length;
x=num[r];
i=p-1;
bak=0;
printf("inside the partition\n");
printf("length of june recieved =%d \n",june);
for(j=0;j<=r-1;j++)
{
if(num[j]<=x)
{
i=i+1;
temp=num[i];
num[i]=num[j];
num[j]=temp;
printf("printing array after swap\n");
for(;bak<7;bak++)
{
printf(" %d ",num[bak]);
}
}
}
num[i+1]=num[r];
return i+1;
}
void quicksort (int *num,int p,int r,int june)
{
int q,bbc,ccd;
if (p<r)
{
call++;
printf("partition called %d times p=%d r=%d\n",call,p,r);
printf("before sending to function length of june=%d \n",june);
q=partition(num,p,r,june);
bbc=q-1-p+1;
quicksort(num,p,q-1,bbc);
ccd=r-q-1+1;
quicksort(num,q+1,r,ccd);
}
}
But the program is still failing to print the sorted array.
You can compile and run the above code.
SOLVED
Finally with help of replies below I have been able to solve the above problem.
The mistake lied in function partition in statement
for (j = 0; j <= r - 1; j++)
instead it should have been
for (j = p; j <= r - 1; j++)
note j=p and j=0
here
j=0
is wrong since when recursively second partition is tried to be sorted it started disturbing the first partition and hence the result was also wrong.
In this program I faced a problem in using gdb to debug a recursive function.
Please check this thread also
Debugging recurssion was quite tricky.
SO the correct code is
#include<stdio.h>
#include<string.h>
int partition (int *, int, int, int);
void quicksort (int *, int, int, int);
static int call = 0;
int
main ()
{
int i, j, choice;
int length;
int a[] = { 81, 12, 90, 3, 49, 108, 47 };
i = 0;
printf ("the sorted array is\n");
length = sizeof (a) / sizeof (a[0]);
printf ("length of array %d\n", length);
printf ("quick sort called in main\n");
quicksort (a, 0, length - 1, length);
for (i = 0; i < length; i++)
printf (" %d ", a[i]);
}
int
partition (int *num, int p, int r, int june)
{
int x, j, i, temp, bak, length;
x = num[r];
i = p - 1;
bak = 0;
for (j = p; j <= r - 1; j++)
{
if (num[j] <= x)
{
i = i + 1;
temp = num[i];
num[i] = num[j];
num[j] = temp;
}
}
temp=num[i+1];
num[i + 1] = num[r];
num[r]=temp;
return i + 1;
}
void
quicksort (int *num, int p, int r, int june)
{
int q, bbc, ccd;
if (p < r)
{
call++;
q = partition (num, p, r, june);
bbc = q - 1 - p + 1;
quicksort (num, p, q - 1, bbc);
ccd=r-q+1;
quicksort (num, q + 1, r, ccd);
}
}
The problem is in the way you are calculating the length of teh array.......try simply giving the number of elements in the array as the parameter for the quicksort method....i guess u will have the right answer...
and also i agree to the point made....try and passing the length of the array with the array.....try both and tell me which works...:)
NEW CODE:
#include<stdio.h>
#include<string.h>
//int partition (int *,int,int);
void q_sort(int*,int,int);
void quicksort (int *,int);
static int call=0;
int main()
{
int i,j,choice;
int length;
int a[]={81, 12, 90, 3, 49, 108, 47};
i=0;
printf("the sorted array is\n");
length=sizeof(a)/sizeof(a[0]);
printf("length of array %d\n",length);
printf("quick sort called in main\n");
quicksort(a,length);
for(i=0;i<length;i++)
printf (" %d ",a[i]);
}
/*int partition(int *num,int p,int r)
{
int x,j,i,temp,bak,length;
x=num[r];
i=-1;
bak=0;
printf("inside the partition\n");
for(j=0;j<=r-1;j++)
{
if(num[j]<=x)
{
i=i+1;
temp=num[i];
num[i]=num[j];
num[j]=temp;
printf("printing array after swap\n");
for(;bak<7;bak++)
{
printf(" %d ",num[bak]);
}
}
}
num[i+1]=num[r];
return i+1;
}
*/
/*void quicksort (int *num,int p,int r)
{
int q,bbc,ccd;
if (p<r)
{
call++;
printf("partition called %d times p=%d r=%d\n",call,p,r);
q=partition(num,p,r);
bbc=q-1-p+1;
quicksort(num,p,q-1);
ccd=r-q-1+1;
quicksort(num,q+1,r);
}
}*/
void quicksort(int numbers[], int array_size)
{
q_sort(numbers, 0, array_size - 1);
}
void q_sort(int numbers[], int left, int right)
{
int pivot, l_hold, r_hold;
l_hold = left;
r_hold = right;
pivot = numbers[left];
while (left < right)
{
while ((numbers[right] >= pivot) && (left < right))
right--;
if (left != right)
{
numbers[left] = numbers[right];
left++;
}
while ((numbers[left] <= pivot) && (left < right))
left++;
if (left != right)
{
numbers[right] = numbers[left];
right--;
}
}
numbers[left] = pivot;
pivot = left;
left = l_hold;
right = r_hold;
if (left < pivot)
q_sort(numbers, left, pivot-1);
if (right > pivot)
q_sort(numbers, pivot+1, right);
}
You need to put a ; at the end of the function declaration before main:
void pass(int *) ;
^
You have to pass the size of the array along with the array itself. The function receiving the array cannot determine its size. The receiving function only sees num as a pointer, so when you use sizeof(num) it returns the size of the pointer num, not the size of the memory allocated for the array in the main function. So, you have to do something like this:
#include<stdio.h>
void pass(int *, int);
int main ()
{
int a[]={3,5,61,32,12};
int length;
length = sizeof(a)/sizeof(a[0]);
pass(a, length);
}
void pass (int *num, int size)
{
int i;
for (i=0;i<size;i++)
printf(" %d",num[i]);
}
This post explains a similar issue in more detail:
Passing an array as an argument in C++