I am trying to make a merge sort algorithm with the stl library but am having some issues. Below is the code I am using
template <typename Item, typename SizeType>
void merge_sort(Item array[], SizeType size){
size_t n1; //Size of the first subarray
size_t n2; //Size of the second subarray
if(size > 1){
//Compute the size of the subarrays
n1 = size/2;
n2 = size - n1;
//create the temp array.
int* n1Temp = new int[n1];
int* n2Temp = new int[n2];
int i;
for(i = 0; i < n1; i++)
n1Temp[i] = array[i];
for(i = 0; i < n2; i++)
n2Temp[i] = array[i + n1];
//recursive calls
merge_sort(n1Temp, n1);//sort from array[0] through array[n1 - 1]
merge_sort(n2Temp, n2);//sort from array[n1] to the end
//Merge the two sorted halves.
vector<int> v(array, array + size);
merge(n1Temp, n1Temp + n1, n2Temp, n2Temp + n2, v.begin());
copy(v.begin(), v.end(), array);//copy the vector back to the array
delete[] n1Temp;
delete[] n2Temp;
}
}
The code sorts fine but the problem is that it acts like a O(n^2) algorithm instead of O(n \log n), which is due to the creation of the vector in each merge sort call (I think). I tried removing the vector and just using an array in the merge function which can be seen below
//Merge the two sorted halves.
int* finalArray = new int[n1 + n2];
merge(n1Temp, n1Temp + n1, n2Temp, n2Temp + n2, begin(finalArray));
array = finalArray;
But this gets me nothing but errors. Is there any thing I can do to salvage my merge sort algorithm?
As both Vaughn and user93353 pointed out, you should be able to merge directly into the target array at each merge-point. But you can still use std::vector<> to make this significantly easier on yourself.
Also, your temp arrays are of direct type ‘int’, and I’m fairly sure that was intended to be the type of the template parameter
Item. I’m not sure what theSizeTypeparameter is for, but I left it in case you had special ideas for it. Whatever it is, it better be compatible withsize_t:The above technique splits the sub-sequences top-down via copy, then merges in-place the split-copies into the original array. You can reduce this algorithm by one sublist allocation time (but no less space) by doing the splits on the original array, then merging into temp-space and copying after, which i think you were trying to do in the first place:
General Iterator-Based Solution
For a general solution that allows even more flexibility you can define your merge-sort based on iterators rather than Item pointers. It gets a little more hairy, but the benefits are very std-lib-ish.
Finally, if you find yourself sorting a ton of fixed-length C-arrays you may find the following helpful (it uses the general-iterator solution above):
It make the following code rather convenient: