home *** CD-ROM | disk | FTP | other *** search
/ POINT Software Programming / PPROG1.ISO / pascal / visionix / vsortu.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1993-12-29  |  13.0 KB  |  616 lines

  1. {
  2. ════════════════════════════════════════════════════════════════════════════
  3.  
  4. Visionix Sort (VSortu) Unit
  5.    Version 0.7
  6.  Copyright 1991,92,93 Visionix
  7.  ALL RIGHTS RESERVED
  8.  
  9. ────────────────────────────────────────────────────────────────────────────
  10.  
  11.  Revision history in reverse chronological order:
  12.  
  13.  Initials  Date      Comment
  14.  ────────  ────────  ───────────────────────────────────────────────────────
  15.  
  16.  jrt       11/02/93  First logged revision.
  17.  
  18. ════════════════════════════════════════════════════════════════════════════
  19. }
  20.  
  21.  
  22. (*-
  23.  
  24. [TEXT]
  25.  
  26.  
  27. <Overview>
  28.  
  29. This unit implements a generic heap sort routine.
  30.  
  31. This overview will be enhanced in the next BETA release.
  32.  
  33. <Interface>
  34.  
  35. -*)
  36.  
  37. Unit VSortu;
  38.  
  39. Interface
  40.  
  41. Uses
  42.  
  43.   VTypesu,
  44.   VStringu,
  45.   VGenu;
  46.  
  47. {────────────────────────────────────────────────────────────────────────────}
  48.  
  49.  
  50. Type
  51.  
  52.   TSortProc = Function( Var A; Var B ) : SHORTINT;
  53.   PSortProc = ^TSortProc;
  54.  
  55.  
  56. Procedure Sort(               Var Buf;
  57.                                   Index         : WORD;
  58.                                   Count         : WORD;
  59.                                   SortProc      : PSortProc;
  60.                                   Params        : STRING        );
  61.  
  62.  
  63. {────────────────────────────────────────────────────────────────────────────}
  64.  
  65. Implementation
  66.  
  67. Var
  68.  
  69.   SortExSize : WORD;
  70.  
  71.  
  72. Function  shortSortProc(      Var A;
  73.                               Var B             ) : SHORTINT; Far;
  74.  
  75. BEGIN
  76.  
  77.   If ShortInt(A) < ShortInt(B) Then
  78.     shortSortProc := -1
  79.   Else
  80.   If ShortInt(A) > ShortInt(B) Then
  81.     shortSortProc := 1
  82.   Else
  83.     shortSortProc := 0;
  84.  
  85. END;
  86.  
  87. Function  byteSortProc(       Var A;
  88.                               Var B             ) : SHORTINT; Far;
  89.  
  90. BEGIN
  91.  
  92.   If Byte(A) < Byte(B) Then
  93.     byteSortProc := -1
  94.   Else
  95.   If Byte(A) > Byte(B) Then
  96.     byteSortProc := 1
  97.   Else
  98.     byteSortProc := 0;
  99.  
  100. END;
  101.  
  102. Function  intSortProc(        Var A;
  103.                               Var B             ) : SHORTINT; Far;
  104.  
  105. BEGIN
  106.  
  107.   If Integer(A) < Integer(B) Then
  108.     intSortProc := -1
  109.   Else
  110.   If Integer(A) > Integer(B) Then
  111.     intSortProc := 1
  112.   Else
  113.     intSortProc := 0;
  114.  
  115. END;
  116.  
  117. Function  wordSortProc(       Var A;
  118.                               Var B             ) : SHORTINT; Far;
  119.  
  120. BEGIN
  121.  
  122.   If Word(A) < Word(B) Then
  123.     wordSortProc := -1
  124.   Else
  125.   If Word(A) > Word(B) Then
  126.     wordSortProc := 1
  127.   Else
  128.     wordSortProc := 0;
  129.  
  130. END;
  131.  
  132.  
  133. Function  longSortProc(       Var A;
  134.                               Var B             ) : SHORTINT; Far;
  135.  
  136. BEGIN
  137.  
  138.   If LongInt(A) < LongInt(B) Then
  139.     longSortProc := -1
  140.   Else
  141.   If LongInt(A) > LongInt(B) Then
  142.     longSortProc := 1
  143.   Else
  144.     longSortProc := 0;
  145.  
  146. END;
  147.  
  148. Function  strSortProc(        Var A;
  149.                               Var B             ) : SHORTINT; Far;
  150.  
  151. BEGIN
  152.  
  153.   If String(A) < String(B) Then
  154.     strSortProc := -1
  155.   Else
  156.   If String(A) > String(B) Then
  157.     strSortProc := 1
  158.   Else
  159.     strSortProc := 0;
  160.  
  161. END;
  162.  
  163. Function  pstrSortProc(       Var A;
  164.                               Var B             ) : SHORTINT; Far;
  165.  
  166. BEGIN
  167.  
  168.   If String(Pointer(A)^) < String(Pointer(B)^) Then
  169.     pstrSortProc := -1
  170.   Else
  171.   If String(Pointer(A)^) > String(Pointer(B)^) Then
  172.     pstrSortProc := 1
  173.   Else
  174.     pstrSortProc := 0;
  175.  
  176. END;
  177.  
  178.  
  179. Function  pcharSortProc(      Var A;
  180.                               Var B             ) : SHORTINT; Far;
  181.  
  182. Const
  183.  
  184.   NULL = #0;
  185.  
  186. Var
  187.  
  188.   L1   : WORD;
  189.  
  190.   StrA,
  191.   StrB : PCharArray;
  192.  
  193. BEGIN
  194.  
  195.   pcharSortProc := 0;
  196.  
  197.   StrA := PCharArray(Pointer(A));
  198.   StrB := PCharArray(Pointer(B));
  199.  
  200.   If (StrA^[1] = NULL) AND (StrB^[1] = NULL) Then
  201.     Exit;
  202.  
  203.   If (StrA^[1] = NULL) OR (StrB^[1] = NULL) Then
  204.   BEGIN
  205.  
  206.     If ( StrB^[1] = NULL ) Then
  207.       pcharSortProc := -1
  208.     Else
  209.       pcharSortProc := 1;
  210.  
  211.     Exit;
  212.  
  213.   END;
  214.  
  215.   L1 := 1;
  216.  
  217.   While ( StrA^[L1] <> NULL ) AND
  218.         ( StrB^[L1] <> NULL ) AND
  219.         ( StrA^[L1] = StrB^[L1] ) Do
  220.     Inc( L1 );
  221.  
  222.   If ( StrA^[L1] = StrB^[L1] ) Then
  223.     Exit;
  224.  
  225.   If ( StrA^[L1] < StrB^[L1] ) Then
  226.     pcharSortProc := -1
  227.   Else
  228.     pcharSortProc := 1;
  229.  
  230. END;
  231.  
  232. Function  realSortProc(       Var A;
  233.                               Var B             ) : SHORTINT; Far;
  234.  
  235. BEGIN
  236.  
  237.   If Real(A) < Real(B) Then
  238.     realSortProc := -1
  239.   Else
  240.   If Real(A) > Real(B) Then
  241.     realSortProc := 1
  242.   Else
  243.     realSortProc := 0;
  244.  
  245. END;
  246.  
  247. {────────────────────────────────────────────────────────────────────────────}
  248.  
  249. (*-
  250.  
  251. [FUNCTION]
  252.  
  253. Procedure Sort(               Var Buf;
  254.                                   Index         : LONGINT;
  255.                                   Count         : LONGINT;
  256.                                   SortProc      : PSortProc;
  257.                                   Params        : STRING        );
  258.  
  259. [PARAMETERS]
  260.  
  261. Buf         Untyped pointer to the base of the data element array.
  262. Index       Element within array to begin sorting.
  263. Count       Number of elements to sort in the table.
  264. SortProc    Pointer to a comparison function.
  265. Params      Parameter string with specific sorting information.
  266.  
  267. [RETURNS]
  268.  
  269. Buf         Sorted buffer
  270.  
  271. [DESCRIPTION]
  272.  
  273. Sorts a table of data elements using the Heapsort algorithm.  A user-supplied
  274. comparison function is allowed for maximum flexability - but not required for
  275. ShortInt, Byte, Integer, Word, LongInt, String, PString, PChar, and Real
  276. types, which are all auto-formatted.
  277.  
  278. For "user-supplied" types, SortProc should be a function which Sort uses for
  279. element comparisons.  Sort will pass two pointers that address elements in
  280. the table being sorted.  The function should follow the TSortProc template,
  281. where a -1 should be returned if the first parameter is less that the second,
  282. 0 if the two parameters are equal, or +1 if the first parameter is greater
  283. than the second.
  284.  
  285. The parameter string is a string containing a list of specific sorting
  286. instructions to use.  The commands within the Params string must be comma
  287. delimited with no spaces.
  288.  
  289. Parameter substrings are as follows:
  290.  
  291.   ElementType=$    Where $ is the type of element within the table.
  292.                    Default is word type.
  293.  
  294.                    Allowed ElementTypes, preset ElementSize, and
  295.                    kind of element for each include:
  296.  
  297.                    SHORTINT - 1    Ordinals
  298.                    BYTE     - 1    Ordinals
  299.                    INTEGER  - 2    Ordinals
  300.                    WORD     - 2    Ordinals
  301.                    LONGINT  - 4    Ordinals
  302.                    STRING   - 256  Fixed-length (see below)
  303.                    PSTRING  - 4    Pointers for Variant-length
  304.                    PCHAR    - 4    Pointers for Variant-length
  305.                    REAL     - 6    Floating-points
  306.  
  307.                    If the actual ElementSize for a String type is less
  308.                    than 256 (ie. STRING[80]), use ElementSize afterwards to
  309.                    reset to the lesser size.
  310.  
  311.                    If you are using an external compare function, then the
  312.                    ElementType parameter should not be used.
  313.  
  314.   'ElementSize=#'  Where # is the size of each element within the table.
  315.                    Default is 2, the size of a word.  Note that only User
  316.                    types are not precasted in size, and must have this
  317.                    parameter included.
  318.  
  319. [SEE-ALSO]
  320.  
  321. (None)
  322.  
  323. [EXAMPLE]
  324.  
  325. Var
  326.  
  327.   Table : Array[1..5] of STRING;
  328.  
  329. BEGIN
  330.  
  331.   Table[1] := 'ALPHA';
  332.   Table[2] := 'CHARLIE';
  333.   Table[3] := 'ECHO';
  334.   Table[4] := 'DELTA';
  335.   Table[5] := 'BRAVO';
  336.  
  337.   Sort( Table, 1, 5, NIL, 'ElementType=STRING' );
  338.  
  339. END;
  340.  
  341. -*)
  342.  
  343. {────────────────────────────────────────────────────────────────────────────}
  344.  
  345. Procedure Sort(               Var Buf;
  346.                                   Index         : WORD;
  347.                                   Count         : WORD;
  348.                                   SortProc      : PSortProc;
  349.                                   Params        : STRING        );
  350.  
  351. Var
  352.  
  353.   Child       : WORD;
  354.   Cell        : WORD;
  355.   TempBuf     : POINTER;
  356.   ElementSize : WORD;
  357.  
  358.   Param       : STRING;
  359.   ParamField  : STRING;
  360.   ParamData   : STRING;
  361.  
  362.   Left        : WORD;
  363.   Right       : WORD;
  364.  
  365.   DoSort      : TSortProc;
  366.  
  367.   {────────────────────────────────────────────────────────────────────────}
  368.  
  369.   Function RelToAbs( N : WORD ) : WORD;
  370.   BEGIN
  371.  
  372.     RelToAbs := (N * ElementSize) - Pred(ElementSize);
  373.  
  374.   END;
  375.  
  376.   {────────────────────────────────────────────────────────────────────────}
  377.  
  378.   Procedure SiftSort( Parent, Top : WORD );
  379.  
  380.   Var
  381.  
  382.     P1,
  383.     P2  : POINTER;
  384.  
  385.   Label
  386.     Done;
  387.  
  388.   BEGIN
  389.  
  390.     Move( TByteArray(Buf)[RelToAbs(Parent)], TempBuf^, ElementSize );
  391.  
  392.     REPEAT
  393.  
  394.       Child := Parent;
  395.       Inc(Child, Parent);
  396.       If (Child > Top) Then
  397.         Goto Done
  398.  
  399.       Else
  400.       BEGIN
  401.  
  402.         If ( Child < Top ) Then
  403.         BEGIN
  404.  
  405.           P1 := PtrAdd( @Buf, Pred(RelToAbs(Child)) );
  406.           P2 := PtrAdd( @Buf, Pred(RelToAbs(Succ(Child))) );
  407.  
  408.           If ( DoSort( Pointer(P1^), Pointer(P2^) ) = -1 ) Then
  409.             Inc( Child );
  410.  
  411.         END;
  412.  
  413.         {---}
  414.  
  415.         P1 := TempBuf;
  416.         P2 := PtrAdd( @Buf, Pred(RelToAbs(Child)) );
  417.  
  418.         If DoSort( Pointer(P1^), Pointer(P2^) ) = -1 Then
  419.         BEGIN
  420.  
  421.           Move( TByteArray(Buf)[RelToAbs(Child)],
  422.                 TByteArray(Buf)[RelToAbs(Parent)],
  423.                 ElementSize );
  424.  
  425.           Parent := Child;
  426.  
  427.         END
  428.         Else
  429.           Goto Done;
  430.  
  431.       END;
  432.  
  433.     Until (False);
  434.  
  435.     DONE:
  436.  
  437.     Move( TempBuf^,
  438.           TByteArray(Buf)[RelToAbs(Parent)],
  439.           ElementSize );
  440.  
  441.   END;
  442.  
  443.   {────────────────────────────────────────────────────────────────────────}
  444.  
  445. BEGIN
  446.  
  447.   {----------------------}
  448.   { Initialize variables }
  449.   {----------------------}
  450.  
  451.   ElementSize := 2;  { also defaults to sort WORD type }
  452.  
  453.   {------------------------}
  454.   { Parse parameter string }
  455.   {------------------------}
  456.  
  457.   Param := '';
  458.   REPEAT
  459.  
  460.     Param := UpperString( GetNextParam( Param, Params ) );
  461.  
  462.     If Param <> '' Then
  463.     BEGIN
  464.  
  465.       ParamField := GetParamName(Param);
  466.  
  467.       If ParamField = 'ELEMENTSIZE' Then
  468.       BEGIN
  469.  
  470.         ParamData := GetParamData( Param );
  471.         ElementSize := StrToInt( ParamData );
  472.  
  473.       END;
  474.  
  475.       If ParamField = 'ELEMENTTYPE' Then
  476.       BEGIN
  477.  
  478.         ParamData := GetParamData( Param );
  479.  
  480.         If ParamData = 'SHORTINT' Then
  481.         BEGIN
  482.  
  483.           SortProc    := @shortSortProc;
  484.           ElementSize := SizeOf(ShortInt);
  485.  
  486.         END
  487.         Else
  488.  
  489.         If ParamData = 'BYTE' Then
  490.         BEGIN
  491.  
  492.           SortProc    := @byteSortProc;
  493.           ElementSize := SizeOf(Byte);
  494.  
  495.         END
  496.         Else
  497.  
  498.         If ParamData = 'INTEGER' Then
  499.         BEGIN
  500.  
  501.           SortProc    := @intSortProc;
  502.           ElementSize := SizeOf(Integer);
  503.  
  504.         END
  505.         Else
  506.  
  507.         If ParamData = 'WORD' Then
  508.         BEGIN
  509.  
  510.           SortProc    := @wordSortProc;
  511.           ElementSize := SizeOf(Word);
  512.  
  513.         END
  514.         Else
  515.  
  516.         If ParamData = 'LONGINT' Then
  517.         BEGIN
  518.  
  519.           SortProc    := @longSortProc;
  520.           ElementSize := SizeOf(LongInt);
  521.  
  522.         END
  523.         Else
  524.  
  525.         If ParamData = 'STRING' Then
  526.         BEGIN
  527.  
  528.           SortProc    := @strSortProc;
  529.           ElementSize := SizeOf(String);
  530.  
  531.         END
  532.         Else
  533.  
  534.         If ParamData = 'PSTRING' Then
  535.         BEGIN
  536.  
  537.           SortProc    := @pstrSortProc;
  538.           ElementSize := SizeOf(PString);
  539.  
  540.         END
  541.         Else
  542.  
  543.         If ParamData = 'PCHAR' Then
  544.         BEGIN
  545.  
  546.           SortProc    := @pcharSortProc;
  547.           ElementSize := SizeOf(Pointer);
  548.  
  549.         END
  550.         Else
  551.  
  552.         If ParamData = 'REAL' Then
  553.         BEGIN
  554.  
  555.           SortProc    := @realSortProc;
  556.           ElementSize := SizeOf(Real);
  557.  
  558.         END;
  559.  
  560.       END;
  561.  
  562.     END;
  563.  
  564.   UNTIL (Param = '');
  565.  
  566.   {----------------------------------------------}
  567.   { Check to use default sort-checking procedure }
  568.   {----------------------------------------------}
  569.  
  570.   If (SortProc = NIL) Then
  571.     DoSort := wordSortProc
  572.   Else
  573.     DoSort := TSortProc(SortProc);
  574.  
  575.   {-----------------------}
  576.   { Set global SortExSize }
  577.   {-----------------------}
  578.  
  579.   SortExSize := ElementSize;
  580.  
  581.   {------------------}
  582.   { Begin sorting... }
  583.   {------------------}
  584.  
  585.   Left  := Index;
  586.   Right := Index + Pred(Count);
  587.  
  588.   GetMem( TempBuf, ElementSize );
  589.  
  590.   For Cell := (Right DIV 2) DownTo (Succ(Left)) Do
  591.     SiftSort( Cell, Right );
  592.  
  593.   For Cell := Right DownTo Succ(Left) Do
  594.   BEGIN
  595.  
  596.     SiftSort( 1, Cell );
  597.  
  598.     SwapBuffers( TByteArray(Buf)[1],
  599.                  TByteArray(Buf)[RelToAbs(Cell)],
  600.                  ElementSize );
  601.  
  602.   END;
  603.  
  604.   FreeMem( TempBuf, ElementSize );
  605.  
  606. END;
  607.  
  608.  
  609. {────────────────────────────────────────────────────────────────────────────}
  610. {────────────────────────────────────────────────────────────────────────────}
  611. {────────────────────────────────────────────────────────────────────────────}
  612.  
  613.  
  614. BEGIN
  615.  
  616. END.