First thing to note: your array is only four elements long. What happens when your professor asks you to make it 20?
— Do something to replace that
3
on line 5 with a member variable in the class.
Your original code has a buffer overflow on line 9. You seem to have noticed and corrected in the next code, but you are missing the point of recursion.
With iterative stuff, we use a loop and variables to control that loop.
1 2 3 4 5 6 7 8 9
|
void print_iterative( const char* s )
{
int n = 0; // our control variable
while (s[n]) // our don't-exit condition (only quit when s[n] is zero)
{
cout << s[n]; // do stuff
n++; // update our control variable
} // next loop
}
|
To make it recursive, we replace the loop with a function call, and all the variables that control it become arguments to the function.
1 2 3 4 5 6
|
void print_recursive( const char* s, int n ) // the control variable is now an argument
{
if (!s[n]) then return; // the exit condition (negated from the iterative version above)
cout << s[n]; // do stuff
print_recursive( s, n + 1 ); // update our control variable and next loop
}
|
It’s All About The Loops
An insertion sort works over TWO loops
[1]. Given an array of elements indexed [0..N-1] (where N is the number of elements in the array):
• The outer loop is from 1 to N-1, accessing the next element to insert into the sorted sequence.
• The inner loop is to
rotate[2] a portion of the array rightward, from the index where
the element needs inserting to where the element is now.
You can perform recursion on either (or both) of these loops. Take one problem at a time.
Next Element To Insert Loop
Iteratively, that's just:
1 2 3 4 5 6 7
|
void sort()
{
for (int i = 1; i < N; i++)
{
// next element to insert is: array[i]
}
}
|
The control variable is
i
, so that should be an argument to your function. (You have the
array
and
N
variables as part of your class, right?)
1 2 3 4 5 6 7 8
|
void sort_body( int i )
{
if (!(i < N)) then return;
// next element to insert is: array[i]
sort_body( i + 1 );
}
|
Now the
sort() function becomes just:
1 2 3 4
|
void sort()
{
sort_body( 0 );
}
|
Rotate
Here is the iterative part:
1 2 3 4 5 6 7 8 9 10
|
X temp = array[i];
int j = i - 1;
while ((j > 0) and (array[j] > array[i])) // don't-exit conditions
{
array[j+1] = array[j]; // do stuff
j--; // update our control variable
}
array[j] = temp;
|
Dang, that looks quite a bit more complex. Our goal should be to make it as simple as possible.
The first thing we are going to do is NOT mix it up with the other recursion — we will split it off into yet another function.
1 2 3 4 5 6 7 8
|
void sort_body( int i )
{
if (!(i < N)) then return;
sort_rotate( i );
sort_body( i + 1 );
}
|
Hmm, that part
does look much nicer, but now we need to consider what to do with
temp
. That part is
outside the loop, so it should be outside the loop as well:
1 2 3 4 5 6 7 8 9 10
|
void sort_body( int i )
{
if (!(i < N)) then return;
X temp = array[i];
sort_rotate( i );
array[ ? ] = temp; // fooey, a problem.
sort_body( i + 1 );
}
|
The problem is easily solved though. Stop reading a moment and see if you can think any potential solutions.
So, here are two:
• Return the
j
index to
sort().
• Give
sort_rotate() the value so that
sort() doesn’t have to care.
The first solution would look like this:
1 2 3
|
X temp = array[i];
array[ sort_rotate( i ) ] = temp;
|
BTW, do not combine those lines, as the compiler’s optimizer will not play nice with the side effects.
The second solution would look like this:
1 2 3
|
sort_rotate( i, array[i] );
|
Notice the missing temp
variable?
It has moved to a convenient argument of the sort_rotate() function, which sort_rotate() can use before returning (because it found the insertion place or the beginning of the array — the exit conditions).
...
At this point I could write the final solution for you.
But I’m not gonna (at least not for a week or two.)
You have enough here to write a
sort_rotate() function that will take the place of the
j
loop. Do your best, and see how far you get. If you get stuck again, post your current solution (in a new post, please don’t edit your first post), and we’ll help.
[1]
A very simplistic insertion sort can use three loops, but if you, dear reader, have used an additional loop just to find the place to insert, try to figure out how to combine it with the rotate/shift loop.
[2]
A
rotate is like a shift, except that stuff that would be shifted off one end gets stuck on the other. For example:
{ 4, 3, 2, 1 } // original array
{ 1, 4, 3, 2 } // rotated right by one element
You can also see how this is useful in an insertion sort: the item on the right end of the sequence is rotated to the left end, causing everything to shift right one.
This rotation is the core of an insertion sort.
[edits] Stupid BBCode formatting grief...