Reputation: 5002
Yesterday at work I set out to figure out how to sort numbers without using the library method Array.Sort
. I worked on and off when time permitted and finally was able to come up with a basic working algorithm at the end of today. It might be rather stupid and the slowest way, but I am content that I have a working code.
But there is something wrong or missing in the logic, that is causing the output to hang before printing the line: Numbers Sorted. (12/17/2011 2:11:42 AM)
This delay is directly proportionate to the number of elements in the array. To be specific, the output just hangs at the position where I put the tilde in the results section below. The content after tilde is getting printed after that noticeable delay.
Here is the code that does the sort:
while(pass != unsortedNumLen)
{
for(int i=0,j=1; i < unsortedNumLen-1 && j < unsortedNumLen; i++,j++)
{
if (unsorted[i] > unsorted[j])
{
pass = 0;
swaps++;
Console.Write("Swapping {0} and {1}:\t", unsorted[i], unsorted[j]);
tmp = unsorted[i];
unsorted[i] = unsorted[j];
unsorted[j] = tmp;
printArray(unsorted);
}
else pass++;
}
}
The results:
Numbers unsorted. (12/17/2011 2:11:19 AM)
4 3 2 1
Swapping 4 and 3: 3 4 2 1
Swapping 4 and 2: 3 2 4 1
Swapping 4 and 1: 3 2 1 4
Swapping 3 and 2: 2 3 1 4
Swapping 3 and 1: 2 1 3 4
Swapping 2 and 1: 1 2 3 4
~
Numbers sorted. (12/17/2011 2:11:42 AM)
1 2 3 4
Number of swaps: 6
Can you help identify the issue with my attempt?
Link to full code
This is not homework, just me working out.
Upvotes: 4
Views: 1606
Reputation: 56688
Here is the fix:
while(pass < unsortedNumLen)
And here is why the delay occurred.
After the end of the for
loop in which the array was eventually sorted, pass
contains at most unsortedNumLen - 2
(if the last change was between first and second members). But it does not equal the unsorted
array length, so another iteration of while
and inner for
starts. Since the array is sorted unsorted[i] > unsorted[j]
is always false, so pass always gets incremented - exactly the number of times j
got incremented, and that is the unsortedNumLen - 1
. Which is not equal to unsortedNumLen
, and so another iteration of while
begins. Nothing essentially changed, and after this iteration pass
contains 2 * (unsortedNumLen - 1)
, which is still not equal to unsortedNumLen
. And so on.
When pass reaches value int.MaxValue
, it the overflow happens, and next value the variable pass
will get is int.MinValue
. And the process goes on, until pass
finally gets the value unsortedNumLen
at the moment the while
condition is checked. If you are particularly unlucky, this might never happen at all.
P.S. You might want to check out this link.
Upvotes: 2
Reputation: 13837
Change the condition in your while to this:
while (pass < unsortedNumLen)
Logically pass
never equals unsortedNumLen
so your while
won't terminate.
pass
does eventually equal unsortedNumLen
when it goes over the max value of an int
and loops around to it.
In order to see what's happening yourself while it's in the hung state, just hit the pause button in Visual Studio and hover your mouse over pass
to see that it contains a huge value.
You could also set a breakpoint on the while
line and add a watch for pass
. That would show you that the first time the list is sorted, pass
equals 5.
Upvotes: 6
Reputation:
This is just a characteristic of the algorithm you're using to sort. Once it's completed sorting the elements it has no way of knowing the sort is complete, so it does one final pass checking every element again. You can fix this by adding --unsortedNumLen;
at the end of your for loop as follows:
for(int i=0,j=1; i < unsortedNumLen-1 && j < unsortedNumLen; i++,j++)
{
/// existing sorting code
}
--unsortedNumLen;
Reason? Because you algorithm is bubbling the biggest value to the end of the array, there is no need to check this element again since it's already been determined to be larger the all other elements.
Upvotes: 1
Reputation: 14409
It sounds like you want a hint to help you work through it and learn, so I am not posting a complete solution.
Change your else
block to the below and see if it puts you on the right track.
else {
Console.WriteLine("Nothing to do for {0} and {1}", unsorted[i], unsorted[j]);
pass++;
}
Upvotes: 4