Sort Procedures
Rather than just give you BubbleQ sort code, I have included here code for several popular sort algorithms. In each of these, the array to be sorted is named arr and is of type list = array [1..100] of string. The array count is sent through the parameter max. Several of these procedures call upon the procedure swap which you must provide yourself!
BubbleQ Sort
The bubbleq sort makes several passes through the data, just like the bubble sort, exchanging pairs of elements that are out of order. The difference is that rather than swapping items i and i+1, we swap items i and i+gap. In this way, out-of-place elements move farther faster - this is the secret to all the fast sorts. Then on successive passes, we reduce the size of gap until it finally reaches 1, so that final adjustments to the data positions can be made.
PROCEDURE bubbleq (var arr:list; max:integer);
{from Byte, April 1991, p 317}
VAR
i, j, gap : integer;
done : boolean;
BEGIN
gap := max;
REPEAT
done := true;
gap := trunc(gap/1.3);
IF gap<1 THEN
gap := 1;
FOR i:=1 TO max-gap DO
BEGIN
j := i+gap;
IF arr[i]>arr[j] THEN
BEGIN
done := false;
swap(arr[i],arr[j]);
END;
END;
UNTIL (gap=1) AND done;
END;
Shell's Sort
Shell developed this sort procedure in the 60's - the bubbleq sort is really a variation of this classic routine. Like the bubbleq it works by swapping elements that are gap apart, reducing the size of gap on each pass. But on each separate pass, it uses an insertion sort technique rather than a bubble sort. Note the line
gap := max SHR 1;
This line does the same thing as gap := max DIV 2, only faster. Much research has been done on what size gaps to use - this version of Shell's sort uses just one such option.
PROCEDURE shell (var arr:list; max:integer);
VAR
gap, i, j : integer;
BEGIN
gap := max SHR 1;
WHILE gap >= 1 DO
BEGIN
FOR i:= gap+1 TO max DO
BEGIN
j := i-gap;
WHILE j>=1 DO
IF arr[j]<arr[j+gap] THEN
j := 0
ELSE
BEGIN
swap(arr[j],arr[j+gap]);
j := j-gap;
END
END;
gap := gap SHR 1
END;
END;
Insertion Sort
In this variation of the insertion sort, on pass 1 we insert item 2 into its correct position relative to item 1. On pass 2 we insert item 3 into position with (the now sorted) items 1 and 2. On pass k we insert item k+1 into the (sorted) items 1 though k.
PROCEDURE insertion (var arr:list; max:integer);
VAR
j, k, p : integer;
s : string;
BEGIN
FOR j:=2 TO max DO
BEGIN
s := arr[j];
p := j-1;
WHILE (p>0) AND (s<arr[p]) DO
BEGIN
arr[p+1] := arr[p];
p := p-1;
END;
arr[p+1] := s
END
END;
Selection Sort
On pass 1 we scan the entire list looking for the smallest item, and place it in location 1. On pass j we scan the remainder of the list looking for the smallest remaining item, and place it in location j.
PROCEDURE select (var arr:list; max:integer);
VAR
j, k, p : integer;
m : string;
BEGIN
FOR j:=1 TO max-1 DO
BEGIN
m := arr[j];
p := j;
FOR k:=j+1 TO max DO
IF arr[k]<m THEN
BEGIN
m := arr[k];
p := k
END;
arr[p] := arr[j];
arr[j] := m;
END;
END;
Quick Sort
Quicksort uses recursion to sort smaller and smaller pieces
of the target array. By packaging the actual Sort procedure
within the framework of the procedure QuickSort, recursion
overhead is minimized. Nevertheless, this procedure can still
generate a stack/heap collision for certain arrangements of
data. Caution! Since this procedure uses recursion, it can produce devastating results if things go wrong. Be sure to code it carefully if you choose to use it.
PROCEDURE quick (var arr:list; max:integer);
PROCEDURE sort(l,r: integer);
VAR
i, j : integer;
x : string;
BEGIN
i := l;
j := r;
x := arr[(l+r) DIV 2];
REPEAT
WHILE arr[i]<x DO
i := i+1;
WHILE x<arr[j] DO
j := j-1;
IF i<=j THEN
BEGIN
swap(arr[i],arr[j]);
i := i+1;
j := j-1;
END;
UNTIL i>j;
IF l<j THEN
sort(l,j);
IF i<r THEN
sort(i,r);
END;
BEGIN {quicksort};
sort(1,max);
END;
QQuick Sort
This variation on the quick sort also uses recursion, breaking the data into smaller and smaller pieces for sorting. It differs essentially in the order in which the pieces are considered. As with the earlier quick sort code, by packaging the actual qsort procedure within the framework of the procedure qqsort, recursion overhead is minimized. Nevertheless, this procedure can still
generate a stack/heap collision for certain arrangements of
data. Caution! Since this procedure uses recursion, it can produce devastating results if things go wrong. Be sure to code it carefully if you choose to use it.
PROCEDURE qqsort (var arr:list; max:integer);
PROCEDURE qsort(bot,top:integer);
VAR
i, j : integer;
temp : string;
BEGIN
WHILE bot<top DO
BEGIN
i := bot;
j := top;
temp := arr[bot];
WHILE i<j DO
BEGIN
WHILE arr[j]>temp DO
j := j-1;
arr[i] := arr[j];
WHILE (i<j) AND (arr[i]<=temp) DO
i := i+1;
arr[j] := arr[i];
END;
arr[i] := temp;
qsort(bot,i-1);
bot := i+1;
END;
END;
BEGIN
qsort(1,max);
END;