home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / pascal / library / dos / sort / tpsorts / sorts.pas < prev   
Encoding:
Pascal/Delphi Source File  |  1994-04-24  |  14.2 KB  |  489 lines

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