Optimized Merge Algorithm for Merge Sort.
Home
Algorithms
Home
Here I have tried to reduce memory comsumption by using a
queue instead of a temprary
array, and also, I have scrapped the idea of getting the
sorted stuff in the temporary
memory. Instead, I traverse the original array checking
for array elements that are
out of their place, and put it in the queue, so that they
can be put in their proper place
when the time comes. This means that the maximum value of
the queue should never exceed
half the size of the array passed to merge for merging,
but on an average, I still have
to perform some tests for random data to find its average
size, which should never become
half the size of the array unless in the worst case when
all the elements of the 2nd half
of the array exceed the elements of the first half. The
best case is when the data is already
sorted, when absolutely no memory is used.
You can copy the code between the 2 HORIZONTAL LINES, paste it and save
it as ASCII test, and compile it with a standards compliant C++ compiler
such as g++.
void rec_merge_sort (int* data, int first, int last);
void merge_sort (int* data, int size);
void merge_data (int* data_to_merge, const int first, const int last);
void rec_merge_sort (int* data, int first, int last)
{
if (first < last)
{
int mid = (first + last) / 2;
rec_merge_sort (data, first, mid);
rec_merge_sort (data, (mid + 1), last);
merge_data (data, first, last); //assume mid = (first + last) / 2. *it is redundant here......*
}
}
void merge_data (int* data_to_merge, const int first, const int last)
{
queue<int> q; //using a queue instead of a temporary array.
int mid = (first + last) / 2;
int i = first;
int j = mid + 1;
while ((j <= last) && (i <= mid))
{
if (!q.empty ())
{
if ((data_to_merge[j] < data_to_merge[i]) && (data_to_merge[j] < q.front ()))
{
q.push (data_to_merge[i]);
data_to_merge[i++] = data_to_merge[j++];
}
else if ((q.front () < data_to_merge[i]) && (q.front () < data_to_merge[j]))
{
q.push (data_to_merge[i]);
data_to_merge[i++] = q.front ();
q.pop ();
}
else i++;
}
else
{
if (data_to_merge[j] < data_to_merge[i])
{
q.push (data_to_merge[i]);
data_to_merge[i++] = data_to_merge[j++];
}
else i++;
}
}
if (i == mid)
{
if (!q.empty ()) //redundant check!!!, but I need ur opinion on it, cause I'm not too sure.
{
if (q.front () < data_to_merge[i])
{
q.push (data_to_merge[i]);
data_to_merge[i++] = q.front ();
q.pop ();
}
else i++;
}
}
while ((j <= last) && (!q.empty ()))
{
if (q.front () > data_to_merge[j])
{
data_to_merge[i++] = data_to_merge[j++];
}
else
{
data_to_merge[i++] = q.front ();
q.pop ();
}
}
while (j <= last)
data_to_merge[i++] = data_to_merge[j++];
while (!q.empty ())
{
data_to_merge[i++] = q.front ();
q.pop ();
}
}
void merge_sort (int* data, int size)
{
rec_merge_sort (data, 0, (size-1));
}
int main ()
{
int a[] = {-53,-123,-12,10,9,8,7,6,5,4,3,2,1,0};
merge_sort (a, 14);
for (int i = 0; i<14; i++)
{
std::cout<<a[i]<<" ";
}
std::cout<<std::endl;
return (0);
}