0

So I'm trying to implement a Merge-Insertion sort in C++, where the recursive Merge method will be used until the segment length is less than 7, at which point an insertion sort will be used on that segment. My current code is as follows:

#include <iostream>
#include <stdlib.h>

using namespace std;

void print_array(double arr[], int arrLength) {
    int timesToIterate;
    if (arrLength < 25) {
        timesToIterate = 1;
    } else {
        timesToIterate = arrLength/25;
    }
    for (int i = 0; i < timesToIterate; i++) {
        int initialPosition = 25*i;
        int endPosition;
        if (timesToIterate == 1) {
            endPosition = arrLength%25;
        } else {
            endPosition = initialPosition+25;
        }
        cout << "[" << initialPosition << "-" << initialPosition+24 << "]:";
        for (int q = initialPosition; q < endPosition; q++) {
            cout << " " << arr[q];
        }
        cout << endl << endl;
    }
}

void insertion_sort(double arr[], int left, int right) {
    int i, key, j;
    for (i = left+1; i < right; i++) {
        key = arr[i];
        j = i-1;
        while (j >= left && arr[j] > key) {
            arr[j+1] = arr[j];
            j--;
        }
        arr[j+1] = key;
    }
}

void merge(double arr[], int left, int middle, int right) {
    int i, j, k;
    
    //declaration and filling of left and right arrays
    double leftArray[middle-left+1], rightArray[right-middle];
    for (i=0; i < middle-left+1; i++) { leftArray[i] = arr[left+i]; }
    for (i=0; i < right-middle; i++) { rightArray[i] = arr[middle+1+i]; }
    
    //merge two temp arrays into arr while sorting
    i = 0; j = 0; k = left;
    while (i < middle-left+1 && j < right-middle) {
        if (leftArray[i] <= rightArray[j]) { 
            arr[k] = leftArray[i]; i++;
        } else {
            arr[k] = rightArray[j]; j++;
        }
        k++;
    }
    
    //loops to add extra element in left or right array
    while (i < middle-left+1) {
        arr[k] = leftArray[i]; i++; k++;
    }
    while (j < right-middle) {
        arr[k] = rightArray[j]; j++; k++;
    }
}

void merge_sort(double arr[], int left, int right) {
    //base case for if arr is of length 1
    if (right == left) {
        return;
    }
    
    int middle = (left+right)/2;
    
    //use merge sort for segments greater than 6, insertion sort for other
    if (middle-left > 6) {
        merge_sort(arr, left, middle);
    } else {
        insertion_sort(arr, left, middle);
    }
    if (right-middle+1 > 6) {
        merge_sort(arr, middle+1, right);
    } else {
        insertion_sort(arr,middle+1, right);
    }
    
    //merge two segments together, regardless if sorted by merge or insertion
    merge(arr, left, middle, right);
}

int main() {
    int arrLength = 500;
    
    //creation of array of length 500 with random doubles
    double arr[arrLength];
    for (int i = 0; i < arrLength; i++) {
        arr[i] = (((double)(rand() % 20000)) / 10) - 1000;
    }
    
    //printing of initial array
    cout << "Initial Array:" << endl;
    print_array(arr, arrLength);

    //printing of array after sorting
    merge_sort(arr, 0, arrLength-1);
    cout << endl << endl << "Sorted Array:" << endl;
    print_array(arr, arrLength);
    
    return 0;
}

I know for certain that my merge sort function works, and I'm fairly sure that my insertion sort works (although it hasn't been tested separately), but my output is not sorted as it should be. I believe the issue I'm having is in the left and right variables passed for merge sort vs insertion sort, where I'm accidentally overlapping on segments, but I don't know what ranges to pass to insertion sort.

I'm also curious as to if this type of sort can be considered viable to use from a time complexity and memory standpoint. Does implementing insertion sort into merge sort realistically impact the memory that merge sort uses, and if it does at the cost of what kind of time?

  • 1
    *I believe the issue I'm having is in the left and right variables passed for merge sort vs insertion sort, where I'm accidentally overlapping on segments, but I don't know what ranges to pass to insertion sort.* -- All speculation until you use the debugger. Also this: `double arr[arrLength];` is not valid C++. Arrays in C++ must have their sizes denoted by a compile-time value, not a runtime value. Last, why not simply use `std::sort`? – PaulMcKenzie Oct 09 '20 at 00:34
  • If you suspect your insertion sort's ranges are faulty, then create an array and fill it with numbers in reverse order. Print it out. Then choose a sub-range of that array and sort it. Print the array out again. Compare the result to what you expect. Try the same thing, but with numbers already in sorted order. You probably have an off-by-one error or a boundary condition problem somewhere. – paddy Oct 09 '20 at 00:35
  • Also, the [std::is_sorted](https://en.cppreference.com/w/cpp/algorithm/is_sorted) function will tell you if the data is sorted or not. Also again, `double leftArray[middle-left+1], rightArray[right-middle];` -- this is not valid C++. Time to use `std::vector`. – PaulMcKenzie Oct 09 '20 at 00:39
  • To clear a few things: The reason I can't confirm with a debugger is I'm not knowledgeable enough in using GDB to check that. I admit to my own lack of knowledge in that area, since most of my problems come from errors. As for using `std::sort`, the general goal is to implement a merge sort with insertion sort in it. Sort uses a combination of Quicksort, Heapsort, and Insertion sort, which is not what I'm currently trying to achieve. Their are two reasons for use of array: its better use with frequent access of elements, and because this is an assignment which requires use of array. – greenou737 Oct 09 '20 at 00:44
  • *Their are two reasons for use of array* -- The point is that what you have is not valid C++, period. Arrays in C++ must use a compile-time constant -- right now, anyone using an ANSI C++ compiler cannot run your code. If this is what you are being taught, then you're not learning C++. [See this](https://rextester.com/ISSN92407) and [this](https://stackoverflow.com/questions/1887097/why-arent-variable-length-arrays-part-of-the-c-standard) – PaulMcKenzie Oct 09 '20 at 00:49
  • *And I'm fairly sure that my insertion sort works (although it hasn't been tested separately),*. [No, it doesn't work](https://ideone.com/39YwBM) – PaulMcKenzie Oct 09 '20 at 00:59
  • I understand why this program doesn't run on an ANSI C++ compiler, and my school does have us use nothing but vectors pretty much all the time. This assignment however was specified from a time complexity algorithm class, which uses g++ on linux servers, and the program does run there. I'm required to use arrays for this, no matter how much I would love to use vectors (because believe me, I hate using arrays in C++ regardless). As for the insertion sort, I'll take a look at it. Thank you for running that to show that it doesn't work. – greenou737 Oct 09 '20 at 01:05
  • Consider that computers these days are lightning fast. 500 elements is not a good indication of what will be fast or slow, even for a bubble sort. You need to test with an array with thousands of elements. But then the issue becomes this -- if you attempted to test with thousands of elements, you run the risk of blowing out the stack memory with those invalid arrays. We have countless of questions asked here with code that uses the variable-length arrays, and more often than not the issue is the number of elements being declared exhausting the stack memory. – PaulMcKenzie Oct 09 '20 at 01:14
  • In this case I'm instructed to use 500 elements, but in such a case of thousands of elements, would using a merge-insertion algorithm have any preference over a strictly merge sort algorithm? This may not apply directly as a c++ question, but I'm more curious as to the effect of multiple algorithm sorting on runtime/memory in this scenario – greenou737 Oct 09 '20 at 01:19
  • [See this concerning implementation of sorting algorithms using C++](https://stackoverflow.com/questions/24650626/how-to-implement-classic-sorting-algorithms-in-modern-c). You can take the code there and mix / match the various algorithms. – PaulMcKenzie Oct 09 '20 at 01:25

0 Answers0