I am having something that troubles me. I have my implementation of a quick sort algorithm, but when I test it on an array of integers that has over 30 elements, sorting takes, in my opinion to long. Sometimes even more than 10 seconds, unlike with selection sort, insertion sort and bubble sort, which are faster on 10000 elements than quick sort on 100 elements.
Here is my solution, please give advice :)
void kvikSort(int a[], int l, int d) {
int i, k;
if (l >= d)
return;
k = l;
swap(&a[l], &a[(l + d) / 2]);
for (i = l + 1; i <= d; i++)
if (a[i] < a[l])
swap(&a[++k], &a[i]);
swap(&a[l], &a[k]);
kvikSort(a, 0, k-1);
kvikSort(a, k+1, d);
}
EDIT: I am using GCC v 4.7.2 on my Linux Mint 14, proc: intel core2duo e7400
EDIT: My other algorithms:
void selectionSort(int a[], int n) {
int i, j, min;
for (i = 0; i < n - 1; i++) {
min = i;
for (j = i + 1; j < n; j++)
if (a[j] < a[min])
min = j;
if (min != i)
swap(&a[min], &a[i]);
}
}
void insertionSort(int a[], int n) {
int i, j;
for (i = 0; i < n - 1; i++)
for (j = i + 1; j > 0 && a[j] < a[j-1]; j--)
swap(&a[j], &a[j-1]);
}
void bubbleSort(int a[], int n) {
int i, j;
for (i = n - 1; i > 0; i--)
for (j = 0; j < i; j++)
if (a[j] > a[j+1])
swap(&a[j], &a[j+1]);
}
void swap(int *i, int *j) {
int tmp;
tmp = *i;
*i = *j;
*j = tmp;
}
EDIT: Maybe I should mention that in my test program I am first outputing randomly generated array to a text file, then sorted array to another text file. So it is certainly running slow, but that's not the problem, the problem is that quick sort runs a lot slower than the rest.
Your first recursive call
kvikSort(a, 0, k-1);
has the wrong lower bound, it should be
kvikSort(a, l, k-1);
With a lower bound of 0, you re-sort the initial part of the array again and again.
Here's the problem:
void kvikSort(int a[], int l, int d) {
int i, k;
if (l >= d)
return;
k = l;
swap(&a[l], &a[(l + d) / 2]);
for (i = l + 1; i <= d; i++)
if (a[i] < a[l])
swap(&a[++k], &a[i]);
swap(&a[l], &a[k]);
>>> kvikSort(a, 0, k-1);
kvikSort(a, l, k-1);
kvikSort(a, k+1, d);
Related
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
Hello I am working on an application of the merge sort algorithm however after a few hours I am unable to find a solution. Any help or hint would be appreciated. I have tried to debug my code but after many attempts I have not been successful in seeing what the mistake is.
The problem is that the algorithm gives back a wrong result. Example:
input: (10, 5, 16, 2)
output: (2, 5, 5, 10)
#include <stdio.h>
void mergesort(int A[], int l, int r);
void merge(int A[], int l, int q, int r);
int main() {
int n;
scanf("%d", &n);
int tablica[n];
for (int i = 0; i < n; i++)
scanf("%d", &tablica[i]);
mergesort(tablica, 0, n - 1);
for (int i = 0; i < n; i++)
printf("%d ", tablica[i]);
return 0;
}
void mergesort(int A[], int l, int r) {
if (l < r) {
int q = (l + r) / 2;
mergesort(A, l, q);
mergesort(A, q + 1, r);
merge(A, l, q, r);
}
}
void merge(int A[], int l, int q, int r) {
int n = q - l + 1;
int m = r - q;
int B[n];
int C[m];
for (int i = 0; i < n; i++)
B[i] = A[i];
for (int i = 0; i < m; i++)
C[i] = A[q + 1 + i];
int i = 0;
int j = 0;
for (int k = l; k <= r; k++) {
if (B[i] <= C[j] || j >= m) {
A[k] = B[i];
i++;
} else {
A[k] = C[j];
j++;
}
}
}
Without knowing what exactly doesn't work (Does it not compile? Do you get wrong output for some inputs?) it's hard to help. At least one error is here:
if(B[i] <= C[j] || j >= m)
Should be
if(j >= m || i < n && B[i] <= C[j])
It is both important to check j >= m before you check the inequality, and add the i < n check.
Without the latter once you fully consume the B array, B[i] will go beyond the array boundaries, and you will get undefined behavior.
Without the former once j >= m the condition B[i] <= C[j] will be checked before j >= m, also triggering undefined behavior.
UPDATE: with the actual example you provided, the second error narrows down to replacing B[i] = A[i] with B[i] = A[l + i]. With these two changes the example you provided works.
The function merge has several bugs.
For example the size of the array C shall be calculated like
int m = r - q + 1;
instead of
int m = r - q;
Instead of this for loop
for(int i = 0; i < n; i++)
B[i] = A[i];
you have to write
for(int i = 0; i < n; i++)
B[i] = A[l + i];
This if statement
if(B[i] <= C[j] || j >= m)
can result in undefined behavior because there is no check of the validity of the used indices i and j whether they belong to the valid ranges.
The functions can be defined the following way as it is shown in the demonstrative program below.
#include <stdio.h>
void merge( int a[], size_t left, size_t middle, size_t right )
{
size_t n1 = middle - left;
size_t n2 = right - middle;
int a1[n1];
int a2[n2];
for ( size_t i = 0; i < n1; i++ )
{
a1[i] = a[left + i];
}
for ( size_t i = 0; i < n2; i++ )
{
a2[i] = a[middle + i];
}
size_t i = left, i1 = 0, i2 = 0;
while ( i1 < n1 && i2 < n2 )
{
a[i++] = a2[i2] < a1[i1] ? a2[i2++] : a1[i1++];
}
while ( i1 < n1 ) a[i++] = a1[i1++];
while ( i2 < n2 ) a[i++] = a2[i2++];
}
void mergesort( int a[], size_t left, size_t right )
{
if ( left + 1 < right )
{
size_t middle = ( left + right ) / 2;
mergesort( a, left, middle );
mergesort( a, middle, right );
merge( a, left, middle, right );
}
}
int main(void)
{
size_t n;
if ( scanf( "%zu", &n ) == 1 && n != 0 )
{
int a[n];
for ( size_t i = 0; i < n; i++ ) scanf( "%d", a + i );
mergesort( a, 0, n );
for ( size_t i = 0; i < n; i++ )
{
printf( "%d ", a[i] );
}
putchar( '\n' );
}
return 0;
}
If the input is
4
10 5 16 2
then the output will be
2 5 10 16
There is a bug in the merge function:
if (B[i] <= C[j] || j >= m) accesses B[i] and C[j] before testing if i and j are below their respective boundaries. The test should be:
if (i < n && (j >= m || B[i] <= C[j])) {
A[k] = B[i++];
} else {
A[k] = C[j++];
}
Note also these remarks:
you do not need to save the second half of the array because its elements are copied before they get overwritten.
in void mergesort(int A[], int l, int r) r should be excluded, to avoid confusing and error prone +1/-1 adjustments.
similarly, in void merge(int A[], int l, int q, int r), q should be the start of the second half and r the index of the element after the end of the slice.
l looks confusingly similar to 1
Here is a modified version:
#include <stdio.h>
void mergesort(int A[], int low, int high);
void merge(int A[], int low, int mid, int high);
int main() {
int n;
if (scanf("%d", &n) != 1 || n <= 0)
return 1;
int tablica[n];
for (int i = 0; i < n; i++) {
if (scanf("%d", &tablica[i]) != 1)
return 1;
}
mergesort(tablica, 0, n);
for (int i = 0; i < n; i++)
printf("%d ", tablica[i]);
printf("\n");
return 0;
}
void mergesort(int A[], int low, int high) {
if (high - low >= 2) {
int mid = low + (high - low) / 2;
mergesort(A, low, mid);
mergesort(A, mid, high);
merge(A, low, mid, high);
}
}
void merge(int A[], int low, int mid, int high) {
int n = mid - low;
int B[n];
for (int i = 0; i < n; i++)
B[i] = A[low + i];
int i = 0;
int j = mid;
int k = low;
while (i < n) {
if (j >= high || B[i] <= A[j]) {
A[k++] = B[i++];
} else {
A[k++] = C[j++];
}
}
}
I am implementing the Heapsort program in C language which sorts with the binary tree. When I run this program, it is ok until it meets the heapsort function in the program. I also try to debug this but it still gets wrong as meeting the heapsort function.
As referencing some algorithms on the Internet, I find it similar to my source code but they run correctly, so its really hard for me to find out the errors in my source code
#include <stdio.h>
#define MAX 2100
void downheap(int a[], int n, int k)
{
int i=0;
int temp = a[0];
while (k <= n/2)
{
i = k + k;
if(i<n && a[i] <= a[i+1]) i++;
if(temp < a[i]) break;
a[k] = a[i]; k = i;
}
a[k] = temp;
}
void heapsort(int a[], int n)
{
int i, j;
for(i=0; i<=n; i++) downheap(a, n, i);
while(n>=0)
{
j = a[0]; a[0] = a[n]; a[n] = j;
downheap(a, --n, 0);
}
}
int main()
{
int n, a[MAX], i;
printf("Enter your number of elements: ");
scanf("%d", &n);
for(i=0; i<n; i++) printf("%d: ", i), scanf("%d", &a[i]);
heapsort(a, n-1);
for(i=0; i<n; i++) printf("%d ", a[i]);
return 0;
}
There are multiple problems in your code that I list below:
You should stick to the common convention that n is the number of elements. In your code it is the number of elements minus one which is inconvenient. In this case you would call heapsort(a, n).
In the heapsort function, for(i=0; i<=n; i++) downheap(a, n, i) should be for(i=n/2-1; i>=0; i--) downheap(a, n, i).
Next, since n is the number of elements in a, the loop should be while(--n > 0). The iteration where n=0 is pointless since it will then swap a[0] with a[0]. Finally you call downheap(a, n, 0).
The function downheap, is where you have the biggest problem. The function should compare the element at index i with its two children and store the max of the tree at index i. If a swap with a child occurred, resume donwheap with this child. Your function is completely wrong. Here is a correct implementation.
void downheap(int *a, int n, int k){
int l = 2*k+1, r = 2*k+2, max = k;
if (l < n && a[l] > a[max])
max = l;
if (r < n &d a[r] > a[max])
max = r;
if (max != k) {
int j = a[k]; a[k] = a[max]; a[max] = j;
downheap(a, n, max);
}
}
As you can see, this code is very different from yours which is completely wrong.
For your convenience, here is the code of the heapsort function. That code was not as bad, but still incorrect.
void heapsort(int *a, int n){
int i, j;
for(i=n/2-1; i>=0; i--)
downheap(a, n, i);
while(--n > 0){
j = a[0]; a[0] = a[n]; a[n] = j;
downheap(a, n, 0);
}
}
EDIT
Non recursive implementation of downheap:
void downheap(int *a, int n, int k){
while (1) {
int l = 2*k+1, r = 2*k+2, max = k;
if (l < n && a[l] > a[max])
max = l;
if (r < n &d a[r] > a[max])
max = r;
if (max == k)
break;
int j = a[k]; a[k] = a[max]; a[max] = j;
k = max;
}
}
I have changed to quicksort code to sort an array of floats which I got from tutorialgatway.org. However I need the sorted indices. I am aware of the qsort library function that can be used to get the sorted indices and I can implement that. However, I want to avoid standard library (I know this is not recommendation). The reason for not using a standard library is that I need to sort large number of arrays in a loop, which I need to parallelize using openMP, therefore writing function explicitly would allow me to parallelize quicksort function in a loop.
/* C Program for Quick Sort */
#include <stdio.h>
void Swap(float *x, float *y) {
float Temp;
Temp = *x;
*x = *y;
*y = Temp;
}
void quickSort(float a[], int first, int last) {
int i, j;
int pivot;
if (first < last) {
pivot = first;
i = first;
j = last;
while (i < j) {
while (a[i] <= a[pivot] && i < last)
i++;
while (a[j] > a[pivot])
j--;
if (i < j) {
Swap(&a[i], &a[j]);
}
}
Swap(&a[pivot], &a[j]);
quickSort(a, first, j - 1);
quickSort(a, j + 1, last);
}
}
int main() {
int number, i;
float a[100];
printf("\n Please Enter the total Number of Elements : ");
scanf("%d", &number);
printf("\n Please Enter the Array Elements : ");
for (i = 0; i < number; i++)
scanf("%f", &a[i]);
quickSort(a, 0, number - 1);
printf("\n Selection Sort Result : ");
for (i = 0; i < number; i++) {
printf(" %f \t", a[i]);
}
printf("\n");
return 0;
}
How can I return the sorted indices in the code ?
You need to generate an array of indexes from 0 to size-1, then sort the array of indexes according to the array values. So the code does compares using array[index[...]], and does swaps on index[...].
An alternative is to generate an array of pointers from &array[0] to &array[size-1]. When the pointers are sorted, you can convert them to indexes by using: index[i] = pointer[i] - &array[0] (could use a union for the indexes and pointers).
Example program with standard version of Hoare partition scheme to sort array of indexes in I[] according to floats in A[]:
#include <stdio.h>
#include <stdlib.h>
void QuickSort(float A[], size_t I[], size_t lo, size_t hi)
{
if (lo < hi)
{
float pivot = A[I[lo + (hi - lo) / 2]];
size_t t;
size_t i = lo - 1;
size_t j = hi + 1;
while (1)
{
while (A[I[++i]] < pivot);
while (A[I[--j]] > pivot);
if (i >= j)
break;
t = I[i];
I[i] = I[j];
I[j] = t;
}
QuickSort(A, I, lo, j);
QuickSort(A, I, j + 1, hi);
}
}
#define COUNT (4*1024*1024) // number of values to sort
int main(int argc, char**argv)
{
int r; // random number
size_t i;
float * A = (float *) malloc(COUNT*sizeof(float));
size_t * I = (size_t *) malloc(COUNT*sizeof(size_t));
for(i = 0; i < COUNT; i++){ // random floats
r = (((rand()>>4) & 0xff)<< 0);
r += (((rand()>>4) & 0xff)<< 8);
r += (((rand()>>4) & 0xff)<<16);
r += (((rand()>>4) & 0xff)<<24);
A[i] = (float)r;
}
for(i = 0; i < COUNT; i++) // array of indexes
I[i] = i;
QuickSort(A, I, 0, COUNT-1);
for(i = 1; i < COUNT; i++){
if(A[I[i-1]] > A[I[i]]){
printf("error\n");
break;
}
}
free(I);
free(A);
return(0);
}
This version of quicksort avoids stack overflow by only using recursion of the smaller side of the partition. Worst case time complexity will still be O(n^2), but the stack space complexity is limited to O(log(n)).
void QuickSort(float A[], size_t I[], size_t lo, size_t hi)
{
while (lo < hi)
{
float pivot = A[I[lo + (hi - lo) / 2]];
size_t t;
size_t i = lo - 1;
size_t j = hi + 1;
while (1)
{
while (A[I[++i]] < pivot);
while (A[I[--j]] > pivot);
if (i >= j)
break;
t = I[i];
I[i] = I[j];
I[j] = t;
}
/* avoid stack overflow */
if((j - lo) < (hi - j)){
QuickSort(A, I, lo, j);
lo = j+1;
} else {
QuickSort(A, I, j + 1, hi);
hi = j;
}
}
}
I am trying to implement the merge sort algorithm in C. I understand how the algorithm is supposed to work however I am encountering some difficulties with the implementation.
I understand that there are hundreds of examples and source code for it's implementation but I was hoping someone could help me understand why mine is not working correctly.
My code is below and after the code I explain what I have tried so far.
#include <stdio.h>
void merge(int a[], int L[], int R[],int nL, int nR) //nL and nR are the lengths of L[] and R[]
{
int i = 0 , j = 0, k = 0;
while(i<nL && j <nR)
{
if(L[i] <= R[j]){
a[k] = L[i];
i++;
}
else{
a[k] = R[j];
j++;
}
k++;
}
while(i < nL){
a[k] = L[i];
i++;
k++;
}
while(j < nR) {
a[k] = R[j];
j++;
k++;
}
}
void mergesort(int a[],int n) //n is the length of a[]
{
if(n < 2) return; //BASE CASE
int mid = n / 2;
int left[mid];
int right[n-mid];
for(int i = 0; i < mid; i++)
{
left[i] = a[i];
}
for(int i = mid; i < n-1; i++)
{
right[i-mid] = a[i];
}
int nL = sizeof(left) / sizeof(left[0]);
int nR = sizeof(right) / sizeof(right[0]);
mergesort(left, nL);
mergesort(right, nR);
merge(a,left,right,nL,nR);
}
int main(void)
{
printf("Initial:\n");
printf("3 4 1 6\n");
int numbers[4] = {3,4,1,6};
int n = sizeof(numbers) / sizeof(int);
mergesort(numbers,n);
printf("Sorted:\n");
for(int i =0 ; i < 4; i++)
{
printf("%d ", numbers[i]);
}
return 0;
}
As it is and with the unsorted array [3,4,1,6] the output is 0 0 1 3.
Clearly the 1 and 3 are in the right order relative to each other but the two zeros at the beginning are clearly wrong. At first it seemed to me that I was inserting 4 and 6 to the right and out of bounds of the array.
I used some print statements to try and debug but I haven't been able to figure out what was going on. I even tried to follow my code with gdb but I still could not sort it.
Does any one have any ideas of what might be happening?
A more nearly idiomatic way of writing the merge() code would be:
void merge(int a[], int L[], int R[],int nL, int nR)
{
int i = 0, j = 0, k = 0;
while (i < nL && j < nR)
{
if (L[i] <= R[j])
a[k++] = L[i++];
else
a[k++] = R[j++];
}
while (i < nL)
a[k++] = L[i++];
while (j < nR)
a[k++] = R[j++];
}
That's about half the number of lines of your code, and within broad limits, the less code there is to read, the better. There are those who insist on having braces after each loop or conditional. I don't think that's necessary (or particularly helpful), but if that's the style you like, you can use it.
Your mergesort() code is less flabby, but could be changed to:
void mergesort(int a[],int n) //n is the length of a[]
{
if (n < 2)
return; //BASE CASE
int mid = n / 2;
int left[mid];
int right[n-mid];
for (int i = 0; i < mid; i++)
left[i] = a[i];
for (int i = mid; i < n; i++)
right[i-mid] = a[i];
mergesort(left, mid);
mergesort(right, n - mid);
merge(a, left, right, mid, n - mid);
}
This includes the fix for your main problem — the loop loading the right array was leaving the last element uncopied.
With a debugging function such as:
void dump_array(const char *tag, int n, int *a)
{
printf("%s:%d:", tag, n);
for (int i = 0; i < n; i++)
printf(" %3d", a[i]);
putchar('\n');
}
You can do a lot of effective debugging with:
void mergesort(int a[],int n)
{
if (n < 2)
return;
int mid = n / 2;
int left[mid];
int right[n-mid];
dump_array("-->>mergesort()", n, a);
for (int i = 0; i < mid; i++)
left[i] = a[i];
dump_array("left", mid, left);
for (int i = mid; i < n; i++)
right[i-mid] = a[i];
dump_array("right", n - mid, right);
mergesort(left, mid);
dump_array("merged-L", mid, left);
mergesort(right, n - mid);
dump_array("merged-R", n - mid, right);
merge(a, left, right, mid, n - mid);
dump_array("<<--mergesort()", n, a);
}
In your code, the output with the tag right would show 0 or semi-random data for the last element, rather than what you're expecting. This would be a hint as to where the trouble is. Keep the dump_array() function around; it is a useful creature to have. It's a simple-minded version; you can invent more complex versions which outputs a newline at intermediate positions for long arrays, for example.
The issue is in the following code:
for(int i = mid; i < n-1; i++)
{
right[i-mid] = a[i];
}
It should be:
for(int i = mid; i < n; i++) // right should range from mid to n - 1 *inclusive*
{
right[i-mid] = a[i];
}
This is simple implementation of merge sort without any complications. Just pass the array pointer and total number of entires in the array.
void merge(int *a, int top)// Array pointer and max entries
{
int l1, k, l2, u1, u2, size = 1, i, j;
int *sa;
sa = (int *)calloc(top, sizeof(int));
while (size < top)
{
l1 = 0;
k = 0;
while (l1 + size < top)
{
l2 = l1 + size;
u1 = l2 - 1;
u2 = ((l2 + size - 1) < top ? l2 + size - 1 : top - 1);
for (i = l1, j = l2; i <= u1 && j <= u2; )// Merging
{
sa[k++] = a[i] <= a[j] ? a[i++] : a[j++];
}
for ( ; i <= u1; )
sa[k++] = a[i++];
for ( ; j <= u2; )
sa[k++] = a[j++];
l1 = u2 + 1;
}
for (i = l1; i < top; i++) // For the left outs of the process
sa[k++] = a[i];
for (i = 0; i < top; i++)
a[i] = sa[i];
size *= 2;
}
}