First question here, and yes this is a homework question. We are tasked with performing merge sort on an array (which I am familiar with), but in a way I am unsure of how to do. Usually I would have a separate merge and merge sort function, and use the two. However, it sounds like he wants everything in one method? I was just hoping maybe someone could help clear things up for me, or put them into terms I can better understand.
From the assignment:
you will need to implement a non-recursive version of merge-sort algorithm. Arrange two nested loops to accomplish this task. The outer loop should provide the size of segments for merging. The inner loop should take care of selecting positions of segments. The inner loop should start at the left edge and move your segments to the right. Arrange appropriate values of variables left, middle, right, so that sorting is accomplished just by iterating the call merge(a,left,middle,right).
I hate to be so vague, but I really don't understand any of what he's saying. First, what is meant by "outer loop should provide the size of segments"? How does a loop provide anything? What about the next sentence - what does he mean by segments? The data?
I'm not asking for code, but any psuedocode would be really helpful.
If anyone could try and decipher what he means, I'd appreciate it. I've already emailed him about it, but it's been a few hours and I've yet to hear back.
Thank you!
Bottom-up merge sort is a non-recursive variant of the merge sort, in which the array is sorted by a sequence of passes. During each pass, the array is divided into blocks of size m.
Sorting arrays through several computers. Merge Sort is a recursive algorithm with the following recurrence relation for time complexity.
Merge Sort AlgorithmThe recursive version is based on the divide and conquers strategy: Divide: In this step, we divide the input into two halves, the pivot being the midpoint of the array. This step is carried out recursively for all the half arrays until there are no more halves to divide.
It's not so difficult. Consider the recursive merge:
+-+-+-+-+-+-+-+-+
| | | | | | | | |
+-+-+-+-+-+-+-+-+
/ \ split
+-+-+-+-+ +-+-+-+-+
| | | | | | | | | |
+-+-+-+-+ +-+-+-+-+
/ \ / \ split
+-+-+ +-+-+ +-+-+ +-+-+
| | | | | | | | | | | |
+-+-+ +-+-+ +-+-+ +-+-+
/ \ / \ / \ / \ split
+-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+
| | | | | | | | | | | | | | | |
+-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+
\ / \ / \ / \ / merge
+-+-+ +-+-+ +-+-+ +-+-+
| | | | | | | | | | | |
+-+-+ +-+-+ +-+-+ +-+-+
\ / \ / merge
+-+-+-+-+ +-+-+-+-+
| | | | | | | | | |
+-+-+-+-+ +-+-+-+-+
\ / merge
+-+-+-+-+-+-+-+-+
| | | | | | | | |
+-+-+-+-+-+-+-+-+
If you notice, when you split, you don't really do anything. You just tell the recursive function to partially sort the array. Sorting the array consists of first sorting both halves and then merging it. So basically, what you have is this:
+-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+
| | | | | | | | | | | | | | | |
+-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+
\ / \ / \ / \ / merge
+-+-+ +-+-+ +-+-+ +-+-+
| | | | | | | | | | | |
+-+-+ +-+-+ +-+-+ +-+-+
\ / \ / merge
+-+-+-+-+ +-+-+-+-+
| | | | | | | | | |
+-+-+-+-+ +-+-+-+-+
\ / merge
+-+-+-+-+-+-+-+-+
| | | | | | | | |
+-+-+-+-+-+-+-+-+
Now from here it should be obvious. You first merge elements of the array 2 by 2, then 4 by 4, then 8 by 8 etc. That is the outer for
gives you 2, 4, 8, 16, 32, ... (which is what it calls size of the segment because the i
of the loop contains that number) and the inner for
(say with iterator j
) goes over the array, i
by i
merging array[j...j+i/2-1]
with array[j+i/2..j+i-1]
.
I wouldn't write the code since this is homework.
Edit: a picture of how the inner for
works
Imagine if i
is 4, so you are at this stage:
+-+-+ +-+-+ +-+-+ +-+-+
| | | | | | | | | | | |
+-+-+ +-+-+ +-+-+ +-+-+
\ / \ / merge
+-+-+-+-+ +-+-+-+-+
| | | | | | | | | |
+-+-+-+-+ +-+-+-+-+
you will have a for
that once gives you 0
(which is 0*i
) as j
and then 4
(which is 1*i
) as j
. (if i
was 2, you would have j
going like 0, 2, 4, 6)
Now, once you need to merge array[0..1]
with array[2..3]
(which is formulated by array[j..j+i/2-1]
and array[j+i/2..j+i-1]
with j = 0
) and then array[4..5]
with array[6..7]
(which is formulated by the same formulas array[j...j+i/2-1]
and array[j+i/2..j+i-1]
because now j = 4
) That is:
i = 4:
+-+-+-+-+-+-+-+-+
| | | | | | | | |
+-+-+-+-+-+-+-+-+
^ ^ ^ ^ ^ ^ ^ ^
| | | | | | | |
/ / / / \ \ \ \
(j = 0) (j = 4)
| | | | | | | |
j | | | j | | |
| | | j+i-1 | | | j+i-1
| | j+i/2 | | j+i/2
| j+i/2-1 | j+i/2-1
| | | | | | | |
| | | | | | | |
\ / \ / \ / \ /
v v v v
merge merge
Hope this is clear at least a little.
Side help: Just a hint if you don't really know how for
works:
for (statement1; condition; statement2)
{
// processing
}
is like writing
statement1;
while (condition)
{
// processing
statement2;
}
So, if you always wrote
for (int i = 0; i < 10; ++i)
it meant starting from 0, while i
is smaller than 10, do something with i
and then increment it. Now if you want i
to change differently, you just change statement2
such as:
for (int i = 1; i < 1024; i *= 2)
(Try to understand how that final for
works based on its equivalent while
that I wrote you)
std::merge
:template<class InIt, class OutIt>
OutIt mergesort(InIt begin, InIt const end, OutIt o /* auxiliary buffer */)
{
ptrdiff_t j;
for (j = 0; begin != end; ++begin, ++j)
{
for (ptrdiff_t n = 1; n <= j && j % (n * 2) == 0; n *= 2)
{
o = std::merge(o - n * 2, o - n, o - n, o, begin - n * 2);
o = std::swap_ranges(begin - n * 2, begin, o - n * 2);
}
*o = *begin;
++o;
}
--j;
for (ptrdiff_t m = 1, n = 1; n <= j; n *= 2)
{
if (j & n)
{
o = std::merge(o - (m + n), o - m, o - m, o, o - (m + n));
o = std::swap_ranges(begin - (m + n), begin, o - (m + n));
m += n;
}
}
return o;
}
std::inplace_merge
:template<class InIt>
InIt inplace_mergesort(InIt begin, InIt const end)
{
ptrdiff_t j;
for (j = 0; begin != end; ++begin, ++j)
{
for (ptrdiff_t n = 1; n <= j && j % (n * 2) == 0; n *= 2)
{ std::inplace_merge(begin - n * 2, begin - n, begin); }
}
--j;
for (ptrdiff_t m = 1, n = 1; n <= j; n *= 2)
{
if (j & n)
{
std::inplace_merge(begin - (m + n), begin - m, begin);
m += n;
}
}
return begin;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With