0

Code below merges 2 sorted arrays A and B of size n1 and n2 respectively.
Merged output needs to be stored in A.

(No need to go through entire code)
Doubt: While re-allocating A, I am getting a run-time error. Why?

int* temp = (int*)realloc(A,sizeof(int)*(n1+n2));
if(temp != NULL) A = temp;

Code for reference:

void putinend(int* num,int m,int n){
    int i,j;
    for(i=m-1,j=m+n-1;i>=0;i--)
        num[j--] = num[i]; 
}
void merge(int* A, int n1, int* B, int n2) {
    int* temp = (int*)realloc(A,sizeof(int)*(n1+n2));
    if(temp != NULL) A = temp;
    putinend(A,n1,n2);
    int s1=n2,s2=0,i=0;
    while(s1 < n1+n2 && s2 < n2){
        if(A[s1] <= B[s2]) 
            A[i++] = A[s1++];
        else 
            A[i++] = B[s2++];
    }
    while(s1 < n1+n2)
        A[i++] = A[s1++];
    while(s2 < n2)
        A[i++] = B[s2++];
    printf("\n");
    for(i=0;i<10;i++){
        printf("%d ",A[i]);
    }
}
int main() {
    int *A = (int*)malloc(sizeof(int)*8);
    int *B = (int*)malloc(sizeof(int)*2);
    A[0]=1; A[1]=3; A[2] = 5; A[3] = 7; A[4] = 9; A[5] = 11; A[6] = 13; A[7] = 15;
    B[0]=-2; B[1]=2;
    int i;
    merge(A,8,B,2);
    printf("\n");
    for(i=0;i<10;i++){
        printf("%d ",A[i]);
    }
    return 0;
}

Edit: I incorporated corrections given below. But Output returned is

-2 1 2 3 5 7 9 11 13 15 
0 3 5 7 9 11 13 15 0 17 

Why does A change just before returning from merge() and just after returning from merge() in main()?

user3409814
  • 245
  • 1
  • 4
  • 12
  • 2
    You can only `realloc` what you obtained from `malloc` (or `calloc`) or subsequent `realloc` calls. – pmg May 16 '15 at 12:08
  • 3
    @pmg Actually, that's not quite true. If the pointer passed to `realloc` is null, then it functions exactly as `malloc` does. – SevenBits May 16 '15 at 12:50
  • Right! Thanks for the heads up, @SevenBits – pmg May 16 '15 at 14:19
  • when realloc fails, then there is no room in the destination array to be adding characters. Therefore, when realloc fails, the function merge() should either: 1) return with a failure indication or 2) free any malloc'd areas, display a diagnostic message (suggest using 'perror()' and exit the program. – user3629249 May 16 '15 at 21:28
  • in C, do not cast the returned value from malloc() (and family of functions). Always check (!=NULL) the returned value from malloc() (and family of functions) – user3629249 May 16 '15 at 21:30
  • suggest function: merge() return an indication of success/failure. suggest function: main() check that returned value – user3629249 May 16 '15 at 21:32
  • what is the function: putinend() expected to perform? – user3629249 May 16 '15 at 21:41
  • in the merge() function, the 'while()' loops seem to be trying to perform a sort while adding the data from the B[] array. The result is complicated code that doesn't work for all cases. Suggest using memcpy to copy the B[] array into the A[] array, into the newly allocated space. Then perform a insertion sort or bubble sort on the resulting A[] array. – user3629249 May 16 '15 at 21:58
  • this line: 'for(i=0;i<10;i++){' in the merge function will fail to properly output the results if the sum of the number of entries in A[] and B[] does not equal 10. Suggest: 'for(i=0;i<(n1+n2);i++){' – user3629249 May 16 '15 at 22:05
  • regarding this kind of line: 'int s1=n2,s2=0,i=0;' putting more than one statement per line has several undesirable side effects: 1) makes the code more difficult for humans to understand. 2) leaves no room to comment the variables as to their usage and the meaning of the initialization value. Suggest making it a habit of only writing one statement per line. – user3629249 May 16 '15 at 22:14

2 Answers2

1

You call realloc() on an array allocated on the stack. The *alloc() functions work with the heap, though.

From man realloc:

Unless ptr is NULL, it must have been returned by an earlier call to malloc(), calloc() or realloc().

Replace

int A[8];

with something like

int* A = malloc(8 * sizeof(int));

Don't forget to call free() if you need to.

Community
  • 1
  • 1
cadaniluk
  • 15,027
  • 2
  • 39
  • 67
-1

here is the algorithm for a merge sort:

Notice is looks nothing like what the posted code is implementing.

Note: this is a recursive method of implementing a merge sort algorithm

--Merge Sort--

Merge sort is based on Divide and conquer method. It takes the list to be sorted and divide it

in half to create two unsorted lists. The two unsorted lists are then sorted and merged to get a

sorted list. The two unsorted lists are sorted by continually calling the merge-sort algorithm; we

eventually get a list of size 1 which is already sorted. The two lists of size 1 are then merged.

Algorithm:

This is a divide and conquer algorithm. This works as follows –

  1. Divide the input which we have to sort into two parts in the middle. Call it the left part

and right part.

Example: Say the input is -10 32 45 -78 91 1 0 -16 then the left part will be -10 32 45 -

78 and the right part will be 91 1 0 6.

  1. Sort each of them separately. Note that here sort does not mean to sort it using some other

method. We use the same function recursively.

  1. Then merge the two sorted parts.

Input the total number of elements that are there in an array (number_of_elements). Input the

array (array[number_of_elements]). Then call the function MergeSort() to sort the input array.

MergeSort() function sorts the array in the range [left,right] i.e. from index left to index right

inclusive. Merge() function merges the two sorted parts. Sorted parts will be from [left, mid] and

[mid+1, right]. After merging output the sorted array.

MergeSort() function:

It takes the array, left-most and right-most index of the array to be sorted as arguments.

Middle index (mid) of the array is calculated as (left + right)/2. Check if (left

have to sort only when left

by calling MergeSort() function again over the left part MergeSort(array,left,mid) and the right

part by recursive call of MergeSort function as MergeSort(array,mid + 1, right). Lastly merge the

two arrays using the Merge function.

Merge() function:

It takes the array, left-most , middle and right-most index of the array to be merged as

arguments. A temporary array (tempArray[right-left+1]) is required to store the new sorted part.

The current index position (pos) of the temporary array is initialized to 0. The left index position

(lpos) is initialized to left and right index position (rpos) is initialized to mid+1, of the array.

Until lpos < mid and rpos < right

if(array[lpos] < array[rpos]), i.e value of array at position lpos is less than value of

array at position rpos, then store array[lpos] (value at the left index of array) at current

index position (pos) of temporary array and increments the position index (pos) and left

position index (lpos) by 1. tempArray[pos++] = array[lpos++]

Else, store array[rpos] (value at the right index of array) at current index position (pos) of

temporary array and increments the position index (pos) and right position index (rpos)

by 1. tempArray[pos++] = array[rpos++]

Until (lpos <= mid) i.e. elements in the left part of the array are left

tempArray[pos++] = array[lpos++],store array[lpos] (value at the left index of array) at

current index position (pos) of temporary array and increments the position index (pos)

and left position index (lpos) by 1.

Until (rpos <= right) i.e. elements in the right part of the array are left

tempArray[pos++] = array[rpos++],store array[rpos] (value at the right index of array) at

current index position (pos) of temporary array and increments the position index (pos)

and right position index (rpos) by 1.

Finally copy back the sorted array to the original array.

Property:

  1. Best case – When the array is already sorted O(nlogn).

  2. Worst case – When the array is sorted in reverse order O(nlogn).

  3. Average case – O(nlogn).

  4. Extra space is required, so space complexity is O(n) for arrays and O(logn) for linked

lists.

here is an example code, from http://www.thelearningpoint.net/computer-science/arrays-and-sorting-merge-sort--with-c-program-source-code

#include<stdio.h>
/*This is called Forward declaration of function */
void Merge(int * , int , int , int );
/* Logic: This is divide and conquer algorithm. This works as follows.
         (1) Divide the input which we have to sort into two parts in the middle. Call it the left part
              and right part.
             Example: Say the input is  -10 32 45 -78 91 1 0 -16 then the left part will be
             -10 32 45 -78 and the right part will be  91 1 0 6.
         (2) Sort Each of them seperately. Note that here sort does not mean to sort it using some other
              method. We already wrote fucntion to sort it. Use the same.
         (3) Then merge the two sorted parts.
*/
/*This function Sorts the array in the range [left,right].That is from index left to index right inclusive
 */
void MergeSort(int *array, int left, int right)
{
        int mid = (left+right)/2;
        /* We have to sort only when left<right because when left=right it is anyhow sorted*/
        if(left<right)
        {
                /* Sort the left part */
                MergeSort(array,left,mid);
                /* Sort the right part */
                MergeSort(array,mid+1,right);
                /* Merge the two sorted parts */
                Merge(array,left,mid,right);
        }
}
/* Merge functions merges the two sorted parts. Sorted parts will be from [left, mid] and [mid+1, right].
 */
void Merge(int *array, int left, int mid, int right)
{
        /*We need a Temporary array to store the new sorted part*/
        int tempArray[right-left+1];
        int pos=0,lpos = left,rpos = mid + 1;
        while(lpos <= mid && rpos <= right)
        {
                if(array[lpos] < array[rpos])
                {
                        tempArray[pos++] = array[lpos++];
                }
                else
                {
                        tempArray[pos++] = array[rpos++];
                }
        }
        while(lpos <= mid)  tempArray[pos++] = array[lpos++];
        while(rpos <= right)tempArray[pos++] = array[rpos++];
        int iter;
        /* Copy back the sorted array to the original array */
        for(iter = 0;iter < pos; iter++)
        {
                array[iter+left] = tempArray[iter];
        }
        return;
}
int main()
{
        int number_of_elements;
        scanf("%d",&number_of_elements);
        int array[number_of_elements];
        int iter;
        for(iter = 0;iter < number_of_elements;iter++)
        {
                scanf("%d",&array[iter]);
        }
        /* Calling this functions sorts the array */
        MergeSort(array,0,number_of_elements-1);
        for(iter = 0;iter < number_of_elements;iter++)
        {
                printf("%d ",array[iter]);
        }
        printf("\n");
        return 0;
}
user3629249
  • 16,402
  • 1
  • 16
  • 17
  • While this is certainly a long and detailed answer, I'm not sure it ever concisely answers the OP's question in addition to never dealing with the `realloc` issue. Granted, others have answered that portion, but posting a complete description of a merge sort with code doesn't tell the OP what's wrong with what he's done. – David Hoelzer May 16 '15 at 22:32
  • @DavidHoelzer, There was so much convolution and unnecessary complication in the final posted code that I found it much easier (and I suspect more useful to the OP) to just post a correct merge sort algorithm rather than correcting the posted code (with comments) that would only work in certain conditions – user3629249 May 20 '15 at 00:33