|
|
Please support our sponsor:
|
Sorting Viewer
A Visual Basic® Tutorial
Little Battles
|
|
|
As you start a project such as this there must be a glimmer of an idea somewhere in your consciousness. From there on it is all problem solving. In this instance, the only idea I had was that I wanted to show a number of colored bars being sorted. I had no idea what the shape control was, no idea about partitioning, stepping, or speed variation; and I only knew about four sorting methods.
Problems by the numbers for me were:
1. How do you make bars?    
Answer: Discover the Shape control!
Of particular interest to me was the fillcolor property of the shape control. Displaying the RED, ORANGE, GREEN, and BLUE while sorting is really the most striking visual effect of the viewer. After discovering the shape control, considerable time was spent developing the Form_Load sub with attention paid to generating the interface using constants (like UNIT) to allow for easy editing later if the interface didn't have the look and feel I desired. Also if the project was to be of general interest, it was necessary for subsequent users to be able to create the interface in a very simple way (i.e. without having to accurately place and size the controls). After programmatically loading all 16 bars on the form, I knew I was on my way - I knew I could do something like my vision.
Next I started writing the first sort sub - bubble_sort, of course. While I was doing this I was careful to try to make some general subroutines like compar, swap, and pause that would be used by all my future sorting methods. As it turned out the simple pause sub became the heart of the program.
2. How to pause and stop execution    
Answer: A simple loop of DoEvents!
|
Private Sub pause()
Dim i As Long
For i = 1 To Spd
If stepping Or Not sorting Then Exit For
DoEvents
Next
End Sub
|
|
I needed a way to pause the execution of the sorts long enough for the viewer to see the bars being swapped, and I needed to give the user the opportunity to stop the process by clicking a stop button. The Spd (speed) variable eventually would allow the user to vary the pause, and the DoEvents call within the procedure allows the click of another button to be recognized.
Stopping a method was accomplished by setting a Boolean named sorting to true before calling the sorting procedure. Then with strategically placed Exit Sub commands in the sort procedures, I could effectively stop the sorts whenever sorting is false. The pause command came to the rescue again by allowing me to click the stop button which had as its principle statement sorting = False.
In line with making this project a learning tool, one feature I thought would be interesting would be to stop and switch methods right in the middle of a sort. This naturally progressed to just clicking on another sort button without clicking stop. Since all the command buttons are members of the same array, clicking one is like clicking another with the only difference being the Index integer that is the parameter in the Command_Click event sub. This is fine for centralized processing but has one drawback. The first sort will exit out this very sub after the new sort you pick is finished executing. A very messy thread.
3. How to switch sorting methods?    
Answer: Use a temp variable for Index
Let me explain further. When a sort method is clicked, the event is passed to the Command1_Click sub and is then directed to the proper sort procedure with the Select Case block. After that sort is done, the code thread returns to the spot in the Select Case block and continues on down to exit out of Command1_Click (returning control to windows).
|
If sorting Then
sorting = False
idx = Index + 1
Exit Sub
End If
cm1: sorting = True
Select Case Index
Case 5: bubble_sort 0, BARSM1
Case 6: bibub_sort 0, BARSM1
Case 7: count_sort 0, BARSM1
End Select
If idx Then
Index = idx - 1: idx = 0
GoTo cm1
End If
|
|
I needed a way to completely exit one sort method before starting another through this same event sub, or risk unexpected results. To accomplish a sort switch in the Command1_Click sub, I set the boolean sorting to False to get the first sort routine to stop. But before doing this I had to enble the thread of that code as it exited Command_Click to redirect itself to the new sort method. I did this by setting another temp variable equal to the Index of the sort method that I was going to run and then just Exit Sub!
What would happen then is that the first sort would end, and while its thread was exiting Command1_Click, it would encounter the temp Index that would redirect execution back through the Select Case block to do the new sort. If you examine the above code, you will find the name of my temp index is idx.
4. How to accomplish sorting in either direction?    
Answer: Use a global variable indicating direction.
In order to be a versatile sort method, I felt it should be able to arrange the elements in descending as well as ascending order. Granted each sort method must be programmed to know what to do, but there must be a flag telling these routines which direction to go.
In many generic sort routines you will find this information passed to the sort routine as a boolean parameter to the subroutine. This would be in keeping with the encapsulation virtue of OOP. I decided to implement a global integer variable ascend since I prefer to limit the number of parameters that have to be piled onto the stack of recursively called routines.
Note that ascend can be either 1 or -1. This makes it directly useful in the math statements of the sort routines which is something a boolean could not do.
5. How to single step through the sorting?    
Answer: Develop a wait subroutine.
|
Private Sub wait()
stepit = False
Do Until stepit
DoEvents
Loop
End Sub
|
|
Note that stepit is a global boolean. The wait sub calls are judiciously set in routines common to all the sort routines. When the step button is clicked (or when a key is pressed) all that needs to be done is to set stepit = true and the loop will be exited, moving the execution on to the next wait call.
5. How to vary the speed of the sorting?    
Answer: Use a scrollbar control.
|
Private Sub HScroll1_Change()
If Not stepping Then Spd = IHI - HScroll1.Value
End Sub
|
|
Note that IHI is a constant for the intrinsic integer high of 32767 which conveniently happens to be the maximum value a scrollbar will accept. IHI - HScroll1.Value simply inverts the value that the scrollbar has been set to since I need a lower number for Spd when I want to go faster. (Fewer loops means faster execution.) Refer to the code for pause above to see how the change in the Spd variable varies the visual speed of the sorting.
|
|