home *** CD-ROM | disk | FTP | other *** search
- type
- list = array[1..2000] of integer;
- longlist = array[1..3199] of integer;
-
- var
- n : integer; (* number of items to sort *)
- toggle : boolean; (* controls display of list *)
- master : list; (* random values for sorting *)
- a : list; (* working list to be sorted *)
- aux1 : longlist; (* auxiliary arrays used by *)
- aux2 : longlist; (* count and tree sort *)
-
- (* Internal arrays in count and tree sort are forced to overlay aux1 and
- aux2 using the absolute address variable ability of Turbo Pascal. This
- saves some critical space in the program so that large lists can be
- sorted without a heap stack collision. *)
-
-
- (***** COMMON PROCEDURES USED BY SORTING ALGORITHMS *****************)
-
- procedure swap(var i, j : integer);
- var
- t : integer;
- begin
- t := i;
- i := j;
- j := t;
- end;
-
- (***** BUBBLE SORT **************************************************)
-
- (* The list is scanned repeatedly, and adjacent items that are out of
- order are swapped. When a pass occurs with no swaps, the list is
- sorted. *)
-
- procedure bubble(lb, ub : integer);
- var
- swapped : boolean;
- cell : integer;
- begin
- repeat
- swapped := false;
- for cell := lb to ub - 1 do
- begin
- if (a[cell] > a[cell + 1]) then
- begin
- swap(a[cell], a[cell + 1]);
- swapped := true;
- end;
- end;
- until (swapped = false);
- end;
-
- (***** COUNT SORT ***************************************************)
-
- (* An auxiliary array is created with one cell for each item in
- the list, and these cells are set to 1. Each pair of items
- is compared, and the auxiliary cell corresponding to the
- higher item is incremented. The auxiliary cells then give the
- number of items smaller than any given item, which establishes
- its position in the sorted list. *)
-
- procedure count(lb, ub : integer);
- var
- left, right, cell : integer;
- sorted : list absolute aux1;
- count : list absolute aux2;
- begin
- for cell := lb to ub do count[cell] := 1;
- for right := lb + 1 to ub do
- begin
- for left := lb to right - 1 do
- begin
- if (a[right] > a[left])
- then count[right] := count[right] + 1
- else count[left] := count[left] + 1;
- end;
- end;
- for cell := lb to ub do sorted[count[cell]] := a[cell];
- for cell := lb to ub do a[cell] := sorted[cell];
- end;
-
- (***** HEAP SORT ****************************************************)
-
- (* The items are rearranged into a "heap", where each item at position i
- is larger than the two items at positions 2i and 2i + 1. The top item
- in the heap is then repeatedly removed and placed in its final position,
- with the heap being consolidated after each such removal. *)
-
- procedure heap(lb, ub : integer);
- var
- cell : integer;
-
- procedure siftup(parent, top : integer);
- label done;
- var
- child, copy : integer;
- begin
- copy := a[parent];
- repeat
- child := parent + parent;
- if (child > top) then goto done
- else
- begin
- if (child < top) and (a[child] < a[child + 1]) then
- child := child + 1;
- if (a[child] <= copy) then goto done
- else
- begin
- a[parent] := a[child];
- parent := child;
- end;
- end;
- until (false);
- done: a[parent] := copy;
- end;
-
- begin
- for cell := (ub div 2) downto (lb + 1) do siftup(cell, ub);
- for cell := ub downto (lb + 1) do
- begin
- siftup(1, cell);
- swap(a[1], a[cell]);
- end;
- end;
-
- (***** INSERTION SORT ***********************************************)
-
- (* The first item is considered as the nucleus of a sorted lefthand
- sublist. Each succeeding item to the right is compared backward
- along the left sublist and inserted at the correct position in the
- sorted portion. *)
-
- procedure insert(lb, ub : integer);
- var
- cell, newcell, newval : integer;
- begin
- for newcell := lb + 1 to ub do
- begin
- cell := newcell;
- newval := a[cell];
- while (cell > lb) and (newval < a[cell - 1]) do
- begin
- a[cell] := a[cell - 1];
- cell := cell - 1;
- end;
- a[cell] := newval;
- end;
- end;
-
- (***** SIMPLE QUICK SORT *****************************************)
-
- {$A-} (* compiler toggle to allow recursion *)
-
- (* A pivotal value is chosen and the list is rearranged
- so that all values to the left are less than or equal
- to the pivot and all values to the right are greater
- than or equal to the pivot. The same procedure is then
- called recursively to deal with the left and right
- sublists. When all sublists are of length one, the
- list is sorted. In this version, the pivot is simply
- chosen to be the leftmost member of each sublist. *)
-
- procedure quick1(lb, ub : integer);
- var
- left, right, pivot : integer;
- begin
- if (lb < ub) then
- begin
- left := lb;
- right := ub + 1;
- pivot := a[lb];
- repeat
- repeat left := left + 1 until (a[left] >= pivot);
- repeat right := right - 1 until (a[right] <= pivot);
- if (left < right) then swap(a[left], a[right]);
- until (left > right);
- swap(a[lb], a[right]);
- quick1(lb, right - 1);
- quick1(left, ub);
- end;
- end;
-
- (***** IMPROVED QUICK SORT *****************************************)
-
- (* This version includes two improvements: (1) The pivot
- is chosen to be the median of the leftmost, rightmost
- and middle items in each sublist; and (2) sublists of
- less than ten items are left unsorted. The partly sorted
- list can then be rapidly brought into complete order with
- insertion sort. *)
-
- procedure quick2(lb, ub : integer);
- const
- CUTOFF = 10;
- var
- left, right, pivot : integer;
-
- function med(lb, ub : integer) : integer;
- var
- mid : integer;
- begin
- mid := (lb + ub) div 2;
- if (a[lb] <= a[mid]) and (a[mid] <= a[ub]) then med := mid
- else if (a[lb] <= a[ub]) and (a[ub] <= a[mid]) then med := ub
- else med := lb;
- end;
-
- begin
- if (ub - lb > CUTOFF) then
- begin
- left := lb;
- right := ub + 1;
- swap(a[lb], a[med(lb, ub)]);
- pivot := a[lb];
- repeat
- repeat left := left + 1 until (a[left] >= pivot);
- repeat right := right - 1 until (a[right] <= pivot);
- if (left < right) then swap(a[left], a[right]);
- until (left > right);
- swap(a[lb], a[right]);
- quick2(lb, right - 1);
- quick2(left, ub);
- end;
- end;
-
- (***** SIMPLE SELECTION SORT ****************************************)
-
- (* The smallest item is found and placed in the leftmost cell. On each
- succeeding pass, the smallest remaining unsorted item is found and
- placed at the end of the sorted lefthand portion. *)
-
- {procedure select(lb, ub : integer);
- var
- left, right : integer;
- begin
- for left := lb to ub do
- for right := left + 1 to ub do
- if (a[left] > a[right]) then swap(a[left], a[right]);
- end;}
-
- (***** IMPROVED SELECTION SORT **************************************)
-
- (* In this faster version, most calls on swap are replaced by
- an explicit temporary variable, which represents the position
- holding the lowest item yet found at a given time during one
- pass. *)
-
- procedure select(lb, ub : integer);
- var
- left, right, low : integer;
- begin
- for left := lb to ub do
- begin
- low := left;
- for right := left + 1 to ub do
- if (a[right] < a[low]) then low := right;
- swap(a[left], a[low]);
- end;
- end;
-
- (***** SIMPLE SHELL SORT ********************************************)
-
- (* The list is divided into a number of interlaced sublists in which
- items are separated by a gap initially equal to half the length of
- the list. On each pass, the gap is cut in half until on the last
- pass, adjacent items are being compared. During each pass, items
- on each of the current sublists are sorted by insertion sort. *)
-
- {procedure shell(lb, ub : integer);
- var
- gap, left, right : integer;
- begin
- gap := (ub - lb) div 2;
- while (gap >= lb) do
- begin
- for right := gap to ub do
- begin
- left := right - gap;
- while ((left >= lb) and (a[left] > a[left + gap])) do
- begin
- swap(a[left], a[left + gap]);
- left := left - gap;
- end;
- end;
- gap := gap div 2;
- end;
- end;}
-
- (***** IMPROVED SHELL SORT ******************************************)
-
- (* This version saves some time in the inner loop with a better
- version of insertion sort that uses a temporary variable to
- cut down on swaps. *)
-
- procedure shell(lb, ub : integer);
- var
- gap, left, right, newval : integer;
- begin
- gap := (ub - lb) div 2;
- while (gap >= lb) do
- begin
- for right := gap to ub do
- begin
- left := right;
- newval := a[left];
- while (left - gap >= lb) and (newval < a[left - gap]) do
- begin
- a[left] := a[left - gap];
- left := left - gap;
- end;
- a[left] := newval;
- end;
- gap := gap div 2;
- end;
- end;
-
- (***** TREE SORT ****************************************************)
-
- (* In one auxiliary array, the items are arranged in a tree where
- each position i contains a copy of the smaller item at positions
- 2i and 2i + 1. A second auxiliary array contains pointers to the
- original position of each item in the first auxiliary array. The
- first (smallest) item in the tree is repeatedly removed and
- transfered to its final position in the sorted list. Then, it is
- replaced at its original position with a value higher than any
- item in the list, and the tree is rearranged to move the new
- smallest item to the top. *)
-
- procedure tree(lb, ub : integer);
- var
- cell, node : integer;
- value : longlist absolute aux1;
- pointer : longlist absolute aux2;
-
- procedure minimum(cell : integer);
- begin
- if (value[2 * cell] <= value[2 * cell + 1]) then
- begin
- value[cell] := value[2 * cell];
- pointer[cell] := pointer[2 * cell];
- end
- else
- begin
- value[cell] := value[2 * cell + 1];
- pointer[cell] := pointer[2 * cell + 1];
- end;
- end;
-
- begin
- for cell := ub to (2 * ub - 1) do
- begin
- value[cell] := a[cell - ub + 1];
- pointer[cell] := cell;
- end;
- for cell := (ub - 1) downto lb do minimum(cell);
- for cell := lb to ub do
- begin
- a[cell] := value[lb];
- node := pointer[lb];
- value[node] := MAXINT;
- node := node div 2;
- while (node >= lb) do
- begin
- minimum(node);
- node := node div 2;
- end;
- end;
- end;
-
- (***** MAIN PROGRAM INFRASTRUCTURE **********************************)
-
- procedure reset(n : integer);
- var
- i : integer;
- begin
- for i := 1 to n + 1 do a[i] := master[i];
- end;
-
- procedure init(var n : integer);
- var
- i : integer;
- begin
- writeln;
- write('Number of items to sort: ');
- readln(n);
- for i := 1 to n do master[i] := random(2000);
- master[n + 1] := MAXINT;
- reset(n);
- end;
-
- procedure presort(n : integer);
- var
- i : integer;
- begin
- quick2(1, n);
- for i := 1 to n do master[i] := a[i];
- end;
-
- procedure show(n : integer);
- var
- i : integer;
- begin
- writeln;
- for i := 1 to n do
- begin
- write(a[i] : 5);
- if (i mod 10 = 0) then writeln;
- end;
- end;
-
- procedure dosort(c : char);
- begin
- reset(n);
- if (toggle) then show(n);
- writeln;
- write('ready?');
- repeat until keypressed;
- write(' begin');
- case c of
- 'B' : bubble(1, n);
- 'C' : count(1, n);
- 'H' : heap(1, n);
- 'I' : insert(1, n);
- 'L' : shell(1, n);
- 'Q' : quick1(1, n);
- 'R' : begin quick2(1, n); insert(1, n); end;
- 'S' : select(1, n);
- 'T' : tree(1, n);
- end;
- writeln(' end');
- if (toggle) then show(n);
- end;
-
- procedure menu;
- var
- c : char;
- begin
- writeln;
- write('Options:');
- writeln;
- writeln;
- writeln(' ' : 10, 'B Bubble sort.');
- writeln(' ' : 10, 'C Count sort.');
- writeln(' ' : 10, 'D toggle Display of list.');
- writeln(' ' : 10, 'H Heap sort.');
- writeln(' ' : 10, 'I Insertion sort.');
- writeln(' ' : 10, 'L sheLL sort.');
- writeln(' ' : 10, 'N Number of items to sort.');
- writeln(' ' : 10, 'P Presort master list.');
- writeln(' ' : 10, 'Q Quick sort.');
- writeln(' ' : 10, 'R quick sort 2.');
- writeln(' ' : 10, 'S Selection sort.');
- writeln(' ' : 10, 'T Tree sort.');
- writeln(' ' : 10, 'X eXit program.');
- writeln;
- write('Your choice? ');
- read(kbd, c);
- c := upcase(c);
- writeln;
- case c of
- 'B', 'C', 'H', 'I', 'L', 'Q', 'R', 'S', 'T' : dosort(c);
- 'D' : toggle := not toggle;
- 'N' : init(n);
- 'P' : presort(n);
- 'X' : halt;
- else
- begin
- writeln;
- writeln('Not on menu.');
- end;
- end;
- menu;
- end;
-
- (***** MAIN PROGRAM *************************************************)
-
- begin
- toggle := true;
- menu;
- end.