home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PASCAL / TPSORTS.ZIP / SORTS.PAS < prev   
Encoding:
Pascal/Delphi Source File  |  1986-05-14  |  14.1 KB  |  482 lines

  1. type
  2.     list = array[1..2000] of integer;
  3.     longlist = array[1..3199] of integer;
  4.  
  5. var
  6.     n        : integer;                      (* number of items to sort   *)
  7.     toggle   : boolean;                      (* controls display of list  *)
  8.     master   : list;                         (* random values for sorting *)
  9.     a        : list;                         (* working list to be sorted *)
  10.     aux1     : longlist;                     (* auxiliary arrays used by  *)
  11.     aux2     : longlist;                     (* count and tree sort       *)
  12.  
  13. (*  Internal arrays in count and tree sort are forced to overlay aux1 and
  14.     aux2 using the absolute address variable ability of Turbo Pascal.  This
  15.     saves some critical space in the program so that large lists can be
  16.     sorted without a heap stack collision.  *)
  17.  
  18.  
  19. (***** COMMON PROCEDURES USED BY SORTING ALGORITHMS *****************)
  20.  
  21. procedure swap(var i, j : integer);
  22.     var
  23.         t : integer;
  24. begin
  25.     t := i;
  26.     i := j;
  27.     j := t;
  28. end;
  29.  
  30. (***** BUBBLE SORT **************************************************)
  31.  
  32. (*  The list is scanned repeatedly, and adjacent items that are out of
  33.     order are swapped.  When a pass occurs with no swaps, the list is
  34.     sorted.  *)
  35.  
  36. procedure bubble(lb, ub : integer);
  37.     var
  38.         swapped : boolean;
  39.         cell    : integer;
  40. begin
  41.     repeat
  42.         swapped := false;
  43.         for cell := lb to ub - 1 do
  44.         begin
  45.             if (a[cell] > a[cell + 1]) then
  46.             begin
  47.                 swap(a[cell], a[cell + 1]);
  48.                 swapped := true;
  49.             end;
  50.         end;
  51.     until (swapped = false);
  52. end;
  53.  
  54. (***** COUNT SORT ***************************************************)
  55.  
  56. (*  An auxiliary array is created with one cell for each item in
  57.     the list, and these cells are set to 1.  Each pair of items
  58.     is compared, and the auxiliary cell corresponding to the
  59.     higher item is incremented.  The auxiliary cells then give the
  60.     number of items smaller than any given item, which establishes
  61.     its position in the sorted list.  *)
  62.  
  63. procedure count(lb, ub : integer);
  64.     var
  65.         left, right, cell : integer;
  66.         sorted            : list absolute aux1;
  67.         count             : list absolute aux2;
  68. begin
  69.     for cell := lb to ub do count[cell] := 1;
  70.     for right := lb + 1 to ub do
  71.     begin
  72.         for left := lb to right - 1 do
  73.         begin
  74.             if (a[right] > a[left])
  75.             then count[right] := count[right] + 1
  76.             else count[left]  := count[left]  + 1;
  77.         end;
  78.     end;
  79.     for cell := lb to ub do sorted[count[cell]] := a[cell];
  80.     for cell := lb to ub do a[cell] := sorted[cell];
  81. end;
  82.  
  83. (***** HEAP SORT ****************************************************)
  84.  
  85. (*  The items are rearranged into a "heap", where each item at position i
  86.     is larger than the two items at positions 2i and 2i + 1.  The top item
  87.     in the heap is then repeatedly removed and placed in its final position,
  88.     with the heap being consolidated after each such removal.  *)
  89.  
  90. procedure heap(lb, ub : integer);
  91.     var
  92.         cell : integer;
  93.  
  94.     procedure siftup(parent, top : integer);
  95.         label done;
  96.         var
  97.             child, copy : integer;
  98.     begin
  99.         copy := a[parent];
  100.         repeat
  101.             child := parent + parent;
  102.             if (child > top) then goto done
  103.             else
  104.             begin
  105.                 if (child < top) and (a[child] < a[child + 1]) then
  106.                     child := child + 1;
  107.                 if (a[child] <= copy) then goto done
  108.                 else
  109.                 begin
  110.                     a[parent] := a[child];
  111.                     parent := child;
  112.                 end;
  113.             end;
  114.         until (false);
  115.         done:    a[parent] := copy;
  116.     end;
  117.  
  118. begin
  119.     for cell := (ub div 2) downto (lb + 1) do siftup(cell, ub);
  120.     for cell := ub downto (lb + 1) do
  121.     begin
  122.         siftup(1, cell);
  123.         swap(a[1], a[cell]);
  124.     end;
  125. end;
  126.  
  127. (***** INSERTION SORT ***********************************************)
  128.  
  129. (*  The first item is considered as the nucleus of a sorted lefthand
  130.     sublist.  Each succeeding item to the right is compared backward
  131.     along the left sublist and inserted at the correct position in the
  132.     sorted portion.  *)
  133.  
  134. procedure insert(lb, ub : integer);
  135.     var
  136.         cell, newcell, newval : integer;
  137. begin
  138.     for newcell := lb + 1 to ub do
  139.     begin
  140.         cell := newcell;
  141.         newval := a[cell];
  142.         while (cell > lb) and (newval < a[cell - 1]) do
  143.         begin
  144.             a[cell] := a[cell - 1];
  145.             cell := cell - 1;
  146.         end;
  147.         a[cell] := newval;
  148.     end;
  149. end;
  150.  
  151. (***** SIMPLE QUICK SORT *****************************************)
  152.  
  153. {$A-}  (* compiler toggle to allow recursion *)
  154.  
  155. (*  A pivotal value is chosen and the list is rearranged
  156.     so that all values to the left are less than or equal
  157.     to the pivot and all values to the right are greater
  158.     than or equal to the pivot.  The same procedure is then
  159.     called recursively to deal with the left and right
  160.     sublists.  When all sublists are of length one, the
  161.     list is sorted.  In this version, the pivot is simply
  162.     chosen to be the leftmost member of each sublist. *)
  163.  
  164. procedure quick1(lb, ub : integer);
  165.     var
  166.         left, right, pivot : integer;
  167. begin
  168.     if (lb < ub) then
  169.     begin
  170.         left := lb;
  171.         right := ub + 1;
  172.         pivot := a[lb];
  173.         repeat
  174.             repeat left  := left  + 1 until (a[left]  >= pivot);
  175.             repeat right := right - 1 until (a[right] <= pivot);
  176.             if (left < right) then swap(a[left], a[right]);
  177.         until (left > right);
  178.         swap(a[lb], a[right]);
  179.         quick1(lb, right - 1);
  180.         quick1(left, ub);
  181.     end;
  182. end;
  183.  
  184. (***** IMPROVED QUICK SORT *****************************************)
  185.  
  186. (*  This version includes two improvements:  (1) The pivot
  187.     is chosen to be the median of the leftmost, rightmost
  188.     and middle items in each sublist; and (2) sublists of
  189.     less than ten items are left unsorted.  The partly sorted
  190.     list can then be rapidly brought into complete order with
  191.     insertion sort.  *)
  192.  
  193. procedure quick2(lb, ub : integer);
  194.     const
  195.         CUTOFF = 10;
  196.     var
  197.         left, right, pivot : integer;
  198.  
  199.     function med(lb, ub : integer) : integer;
  200.     var
  201.         mid : integer;
  202.     begin
  203.         mid := (lb + ub) div 2;
  204.         if (a[lb] <= a[mid]) and (a[mid] <= a[ub]) then med := mid
  205.         else if (a[lb] <= a[ub]) and (a[ub] <= a[mid]) then med := ub
  206.         else med := lb;
  207.     end;
  208.  
  209. begin
  210.     if (ub - lb > CUTOFF) then
  211.     begin
  212.         left := lb;
  213.         right := ub + 1;
  214.         swap(a[lb], a[med(lb, ub)]);
  215.         pivot := a[lb];
  216.         repeat
  217.             repeat left  := left  + 1 until (a[left]  >= pivot);
  218.             repeat right := right - 1 until (a[right] <= pivot);
  219.             if (left < right) then swap(a[left], a[right]);
  220.         until (left > right);
  221.         swap(a[lb], a[right]);
  222.         quick2(lb, right - 1);
  223.         quick2(left, ub);
  224.     end;
  225. end;
  226.  
  227. (***** SIMPLE SELECTION SORT ****************************************)
  228.  
  229. (*  The smallest item is found and placed in the leftmost cell.  On each
  230.     succeeding pass, the smallest remaining unsorted item is found and
  231.     placed at the end of the sorted lefthand portion.  *)
  232.  
  233. {procedure select(lb, ub : integer);
  234.     var
  235.         left, right : integer;
  236. begin
  237.     for left := lb to ub do
  238.         for right := left + 1 to ub do
  239.             if (a[left] > a[right]) then swap(a[left], a[right]);
  240. end;}
  241.  
  242. (***** IMPROVED SELECTION SORT **************************************)
  243.  
  244. (*  In this faster version, most calls on swap are replaced by
  245.     an explicit temporary variable, which represents the position
  246.     holding the lowest item yet found at a given time during one
  247.     pass.  *)
  248.  
  249. procedure select(lb, ub : integer);
  250.     var
  251.         left, right, low : integer;
  252. begin
  253.     for left := lb to ub do
  254.     begin
  255.         low := left;
  256.         for right := left + 1 to ub do
  257.             if (a[right] < a[low]) then low := right;
  258.         swap(a[left], a[low]);
  259.     end;
  260. end;
  261.  
  262. (***** SIMPLE SHELL SORT ********************************************)
  263.  
  264. (*  The list is divided into a number of interlaced sublists in which
  265.     items are separated by a gap initially equal to half the length of
  266.     the list.  On each pass, the gap is cut in half until on the last
  267.     pass, adjacent items are being compared.  During each pass, items
  268.     on each of the current sublists are sorted by insertion sort.  *)
  269.  
  270. {procedure shell(lb, ub : integer);
  271.     var
  272.         gap, left, right  : integer;
  273. begin
  274.     gap := (ub - lb) div 2;
  275.     while (gap >= lb) do
  276.     begin
  277.         for right := gap to ub do
  278.         begin
  279.             left := right - gap;
  280.             while ((left >= lb) and (a[left] > a[left + gap])) do
  281.             begin
  282.                 swap(a[left], a[left + gap]);
  283.                 left := left - gap;
  284.             end;
  285.         end;
  286.         gap := gap div 2;
  287.     end;
  288. end;}
  289.  
  290. (***** IMPROVED SHELL SORT ******************************************)
  291.  
  292. (*  This version saves some time in the inner loop with a better
  293.     version of insertion sort that uses a temporary variable to
  294.     cut down on swaps.  *)
  295.  
  296. procedure shell(lb, ub : integer);
  297.     var
  298.         gap, left, right, newval : integer;
  299. begin
  300.     gap := (ub - lb) div 2;
  301.     while (gap >= lb) do
  302.     begin
  303.         for right := gap to ub do
  304.         begin
  305.             left := right;
  306.             newval := a[left];
  307.             while (left - gap >= lb) and (newval < a[left - gap]) do
  308.             begin
  309.                 a[left] := a[left - gap];
  310.                 left := left - gap;
  311.             end;
  312.             a[left] := newval;
  313.         end;
  314.         gap := gap div 2;
  315.     end;
  316. end;
  317.  
  318. (***** TREE SORT ****************************************************)
  319.  
  320. (*  In one auxiliary array, the items are arranged in a tree where
  321.     each position i contains a copy of the smaller item at positions
  322.     2i and 2i + 1.  A second auxiliary array contains pointers to the
  323.     original position of each item in the first auxiliary array.  The
  324.     first (smallest) item in the tree is repeatedly removed and
  325.     transfered to its final position in the sorted list.  Then, it is
  326.     replaced at its original position with a value higher than any
  327.     item in the list, and the tree is rearranged to move the new
  328.     smallest item to the top.  *)
  329.  
  330. procedure tree(lb, ub : integer);
  331.     var
  332.         cell, node : integer;
  333.         value      : longlist absolute aux1;
  334.         pointer    : longlist absolute aux2;
  335.  
  336.     procedure minimum(cell : integer);
  337.     begin
  338.         if (value[2 * cell] <= value[2 * cell + 1]) then
  339.         begin
  340.             value[cell] := value[2 * cell];
  341.             pointer[cell] := pointer[2 * cell];
  342.         end
  343.         else
  344.         begin
  345.             value[cell] := value[2 * cell + 1];
  346.             pointer[cell] := pointer[2 * cell + 1];
  347.         end;
  348.     end;
  349.  
  350. begin
  351.     for cell := ub to (2 * ub - 1) do
  352.     begin
  353.         value[cell] := a[cell - ub + 1];
  354.         pointer[cell] := cell;
  355.     end;
  356.     for cell := (ub - 1) downto lb do minimum(cell);
  357.     for cell := lb to ub do
  358.     begin
  359.         a[cell] := value[lb];
  360.         node := pointer[lb];
  361.         value[node] := MAXINT;
  362.         node := node div 2;
  363.         while (node >= lb) do
  364.         begin
  365.             minimum(node);
  366.             node := node div 2;
  367.         end;
  368.     end;
  369. end;
  370.  
  371. (***** MAIN PROGRAM INFRASTRUCTURE **********************************)
  372.  
  373. procedure reset(n : integer);
  374.     var
  375.         i : integer;
  376. begin
  377.     for i := 1 to n + 1 do a[i] := master[i];
  378. end;
  379.  
  380. procedure init(var n : integer);
  381.     var
  382.         i : integer;
  383. begin
  384.     writeln;
  385.     write('Number of items to sort:  ');
  386.     readln(n);
  387.     for i := 1 to n do master[i] := random(2000);
  388.     master[n + 1] := MAXINT;
  389.     reset(n);
  390. end;
  391.  
  392. procedure presort(n : integer);
  393.     var
  394.         i : integer;
  395. begin
  396.     quick2(1, n);
  397.     for i := 1 to n do master[i] := a[i];
  398. end;
  399.  
  400. procedure show(n : integer);
  401.     var
  402.         i : integer;
  403. begin
  404.     writeln;
  405.     for i := 1 to n do
  406.     begin
  407.         write(a[i] : 5);
  408.         if (i mod 10 = 0) then writeln;
  409.     end;
  410. end;
  411.  
  412. procedure dosort(c : char);
  413. begin
  414.     reset(n);
  415.     if (toggle) then show(n);
  416.     writeln;
  417.     write('ready?');
  418.     repeat until keypressed;
  419.     write('    begin');
  420.     case c of
  421.         'B' : bubble(1, n);
  422.         'C' : count(1, n);
  423.         'H' : heap(1, n);
  424.         'I' : insert(1, n);
  425.         'L' : shell(1, n);
  426.         'Q' : quick1(1, n);
  427.         'R' : begin quick2(1, n); insert(1, n); end;
  428.         'S' : select(1, n);
  429.         'T' : tree(1, n);
  430.     end;
  431.     writeln('    end');
  432.     if (toggle) then show(n);
  433. end;
  434.  
  435. procedure menu;
  436.     var
  437.         c : char;
  438. begin
  439.     writeln;
  440.     write('Options:');
  441.     writeln;
  442.     writeln;
  443.     writeln(' ' : 10, 'B  Bubble sort.');
  444.     writeln(' ' : 10, 'C  Count sort.');
  445.     writeln(' ' : 10, 'D  toggle Display of list.');
  446.     writeln(' ' : 10, 'H  Heap sort.');
  447.     writeln(' ' : 10, 'I  Insertion sort.');
  448.     writeln(' ' : 10, 'L  sheLL sort.');
  449.     writeln(' ' : 10, 'N  Number of items to sort.');
  450.     writeln(' ' : 10, 'P  Presort master list.');
  451.     writeln(' ' : 10, 'Q  Quick sort.');
  452.     writeln(' ' : 10, 'R  quick sort 2.');
  453.     writeln(' ' : 10, 'S  Selection sort.');
  454.     writeln(' ' : 10, 'T  Tree sort.');
  455.     writeln(' ' : 10, 'X  eXit program.');
  456.     writeln;
  457.     write('Your choice?  ');
  458.     read(kbd, c);
  459.     c := upcase(c);
  460.     writeln;
  461.     case c of
  462.         'B', 'C', 'H', 'I', 'L', 'Q', 'R', 'S', 'T' : dosort(c);
  463.         'D' : toggle := not toggle;
  464.         'N' : init(n);
  465.         'P' : presort(n);
  466.         'X' : halt;
  467.         else
  468.         begin
  469.             writeln;
  470.             writeln('Not on menu.');
  471.         end;
  472.     end;
  473.     menu;
  474. end;
  475.  
  476. (***** MAIN PROGRAM *************************************************)
  477.  
  478. begin
  479.     toggle := true;
  480.     menu;
  481. end.
  482.