MMSEARCH.PAS
上传用户:hylc_2004
上传日期:2014-01-23
资源大小:46800k
文件大小:9k
源码类别:

Delphi控件源码

开发平台:

Delphi

  1. {========================================================================}
  2. {=                (c) 1995-98 SwiftSoft Ronald Dittrich                 =}
  3. {========================================================================}
  4. {=                          All Rights Reserved                         =}
  5. {========================================================================}
  6. {=  D 01099 Dresden             = Tel.: +0351-8012255                   =}
  7. {=  Loewenstr.7a                = info@swiftsoft.de                     =}
  8. {========================================================================}
  9. {=  Actual versions on http://www.swiftsoft.de/mmtools.html             =}
  10. {========================================================================}
  11. {=  This code is for reference purposes only and may not be copied or   =}
  12. {=  distributed in any format electronic or otherwise except one copy   =}
  13. {=  for backup purposes.                                                =}
  14. {=                                                                      =}
  15. {=  No Delphi Component Kit or Component individually or in a collection=}
  16. {=  subclassed or otherwise from the code in this unit, or associated   =}
  17. {=  .pas, .dfm, .dcu, .asm or .obj files may be sold or distributed     =}
  18. {=  without express permission from SwiftSoft.                          =}
  19. {=                                                                      =}
  20. {=  For more licence informations please refer to the associated        =}
  21. {=  HelpFile.                                                           =}
  22. {========================================================================}
  23. {=  $Date: 20.01.1998 - 18:00:00 $                                      =}
  24. {========================================================================}
  25. unit MMSearch;
  26. {$I COMPILER.INC}
  27. interface
  28. uses SysUtils;
  29. type
  30.    TCompareFunc = function(p1, p2: Pointer): integer;
  31. function  bsearch(key, base: Pointer; nelem, width: integer; fcmp: TCompareFunc): Pointer;
  32. function  lsearch(key, base: Pointer; var nelem: integer; width: integer; fcmp: TCompareFunc): Pointer;
  33. function  lfind(key, base: Pointer; nelem, width: integer; fcmp: TCompareFunc): Pointer;
  34. procedure qsort(pBase: Pointer; nElem, width: integer; fcmp: TCompareFunc);
  35. implementation
  36. var
  37.    qWidth: integer;
  38. (*======================================================================*)
  39. (* bsearch - binary search                                              *)
  40. (*======================================================================*)
  41. function bsearch(key, base: Pointer; nelem, width: integer; fcmp: TCompareFunc): Pointer;
  42. var
  43.    kmin, probe: PChar;
  44.    i, j: integer;
  45. begin
  46.    kmin := base;
  47.    while (nelem > 0) do
  48.    begin
  49.       i := nelem shr 1;
  50.       probe := kmin + i * width;
  51.       j := fcmp(key,Probe);
  52.       if (j = 0) then
  53.       begin
  54.          Result := Probe;
  55.          exit;
  56.       end
  57.       else if (j < 0) then nelem := i
  58.       else
  59.       begin
  60.          kmin := probe + width;
  61.          nelem := nelem - i - 1;
  62.       end;
  63.    end;
  64.    Result := nil;
  65. end;
  66. (*======================================================================*)
  67. (* Exchange - exchanges two objects                                     *)
  68. (*======================================================================*)
  69. procedure Exchange(leftP, rightP: Pointer);
  70. var
  71.    i: integer;
  72.    c: char;
  73.    lp,rp: PChar;
  74. begin
  75.    lp := leftP;
  76.    rp := rightP;
  77.    for i := 0 to qWidth-1 do
  78.    begin
  79.       c := rp^;
  80.       rp^ := lp^;
  81.       inc(rp);
  82.       lp^ := c;
  83.       inc(lp);
  84.    end;
  85. end;
  86. (*======================================================================*)
  87. (* qsorthelp                                                            *)
  88. (*======================================================================*)
  89. procedure qsorthelp(pivotP: PChar; nElem: integer; fcmp: TCompareFunc);
  90. label tailRecursion,qbreak;
  91. var
  92.    leftP, rightP, pivotEnd, pivotTemp, leftTemp: PChar;
  93.    lNum, retval: integer;
  94. begin
  95. tailRecursion:
  96.    if (nElem <= 2) then
  97.    begin
  98.       if (nElem = 2) then
  99.       begin
  100.          rightP := qWidth + pivotP;
  101.          if Fcmp(pivotP, rightP) > 0 then Exchange (pivotP, rightP);
  102.       end;
  103.       exit;
  104.    end;
  105.    rightP := (nElem - 1) * qWidth + pivotP;
  106.    leftP  := (nElem shr 1) * qWidth + pivotP;
  107.    { sort the pivot, left, and right elements for "median of 3" }
  108.    if Fcmp(leftP, rightP) > 0 then Exchange(leftP, rightP);
  109.    if Fcmp(leftP, pivotP) > 0 then Exchange(leftP, pivotP)
  110.    else if Fcmp(pivotP, rightP) > 0 then Exchange(pivotP, rightP);
  111.    if (nElem = 3) then
  112.    begin
  113.       Exchange(pivotP, leftP);
  114.       exit;
  115.    end;
  116.    { now for the classic Hoare algorithm }
  117.    leftP := pivotP + qWidth;
  118.    pivotEnd := leftP;
  119.    repeat
  120.         retval := Fcmp(leftP, pivotP);
  121.         while (retval <= 0) do
  122.         begin
  123.            if (retval = 0) then
  124.            begin
  125.               Exchange(leftP, pivotEnd);
  126.               inc(pivotEnd, qWidth);
  127.            end;
  128.            if (leftP < rightP) then inc(leftP, qWidth)
  129.            else goto qBreak;
  130.            retval := Fcmp(leftP, pivotP);
  131.         end;
  132.         while (leftP < rightP) do
  133.         begin
  134.            retval := Fcmp(pivotP, rightP);
  135.            if (retval < 0) then dec(rightP, qWidth)
  136.            else
  137.            begin
  138.               Exchange(leftP, rightP);
  139.               if (retval <> 0) then
  140.               begin
  141.                  inc(leftP, qWidth);
  142.                  dec(rightP, qWidth);
  143.               end;
  144.               break;
  145.            end;
  146.         end;
  147.    until (leftP >= rightP);
  148. qBreak:
  149.    if Fcmp(leftP, pivotP) <= 0 then leftP := leftP + qWidth;
  150.    leftTemp := leftP - qWidth;
  151.     pivotTemp := pivotP;
  152.     while (pivotTemp < pivotEnd) and (leftTemp >= pivotEnd) do
  153.     begin
  154.        Exchange(pivotTemp, leftTemp);
  155.        inc(pivotTemp, qWidth);
  156.        dec(leftTemp, qWidth);
  157.     end;
  158.     lNum := (leftP - pivotEnd) div qWidth;
  159.     nElem := ((nElem * qWidth + pivotP) - leftP) div qWidth;
  160.     { Sort smaller partition first to reduce stack usage }
  161.     if (nElem < lNum) then
  162.     begin
  163.        qSortHelp(leftP, nElem, fcmp);
  164.        nElem := lNum;
  165.     end
  166.     else
  167.     begin
  168.        qSortHelp(pivotP, lNum, fcmp);
  169.        pivotP := leftP;
  170.     end;
  171.     goto tailRecursion;
  172. end;
  173. (*======================================================================*)
  174. (* qsort - sorts using the quick sort routine                           *)
  175. (*======================================================================*)
  176. procedure qsort(pBase: Pointer; nElem, width: integer; fcmp: TCompareFunc);
  177. begin
  178.    qWidth := width;
  179.    if (qWidth = 0) then exit;
  180.    qsorthelp(pBase, nElem, fcmp);
  181. end;
  182. (*======================================================================*)
  183. (* _lsearch - searches a table                                          *)
  184. (*                                                                      *)
  185. (* Description performs lfind or lsearch depending on the value of flag.*)
  186. (*             If flag is 1 it updates the table if no match, if flag   *)
  187. (*             is 0 it only searches.                                   *)
  188. (*======================================================================*)
  189. function _lsearch(key, Base: Pointer; var nelem: integer; width: integer;
  190.                   fcmp: TCompareFunc; Flag: Boolean): Pointer;
  191. var
  192.    Wrk: integer;
  193.    bse: PChar;
  194. begin
  195.    bse := PChar(Base);
  196.    Wrk := nelem;
  197.    while Wrk > 0  do
  198.    begin
  199.       if fcmp(key, bse) = 0 then
  200.       begin
  201.          Result := bse;
  202.          exit;
  203.       end;
  204.       inc(bse, width);
  205.       dec(Wrk);
  206.    end;
  207.    if Flag then
  208.    begin
  209.       inc(nelem);
  210.       move(bse^, PChar(key)^, width);
  211.    end
  212.    else bse := nil;
  213.    Result := bse;
  214. end;
  215. (*======================================================================*)
  216. (* lsearch - searches and updates a table                               *)
  217. (*                                                                      *)
  218. (* Description lfind and lsearch search a table for information. Because*)
  219. (*             these are linear searches, the table entries do not need *)
  220. (*             to be sorted before a call to lfind or lsearch. If the   *)
  221. (*             item that key  points to is not in the table, lsearch    *)
  222. (*             appends that item to the table, but lfind does not.      *)
  223. (*======================================================================*)
  224. function lsearch(key, base: Pointer; var nelem: integer; width: integer;
  225.                  fcmp: TCompareFunc): Pointer;
  226. begin
  227.    Result := _lsearch(key,base,nelem,width,fcmp,True);
  228. end;
  229. (*======================================================================*)
  230. (* lfind - perform a linear search                                      *) 
  231. (*======================================================================*)
  232. function lfind(key, base: Pointer; nelem: integer; width: integer;
  233.                fcmp: TCompareFunc): Pointer;
  234. begin
  235.    Result := _lsearch(key,base,nelem,width,fcmp,False);
  236. end;
  237. end.