sortbase.pp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. {
  2. This file is part of the Free Pascal Run Time Library (rtl)
  3. Copyright (c) 1999-2019 by the Free Pascal development team
  4. This file provides the base for the pluggable sorting algorithm
  5. support. It also provides a default QuickSort implementation.
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. unit sortbase;
  13. {$MODE objfpc}
  14. interface
  15. type
  16. TListSortComparer_NoContext = function(Item1, Item2: Pointer): Integer;
  17. TPtrListSorter_NoContext = procedure(ItemPtrs: PPointer; ItemCount: PtrUInt; Comparer: TListSortComparer_NoContext);
  18. TListSortComparer_Context = function(Item1, Item2, Context: Pointer): Integer;
  19. TPtrListSorter_Context = procedure(ItemPtrs: PPointer; ItemCount: PtrUInt; Comparer: TListSortComparer_Context; Context: Pointer);
  20. PSortingAlgorithm = ^TSortingAlgorithm;
  21. TSortingAlgorithm = record
  22. PtrListSorter_NoContextComparer: TPtrListSorter_NoContext;
  23. PtrListSorter_ContextComparer: TPtrListSorter_Context;
  24. end;
  25. procedure QuickSort_PtrList_NoContext(ItemPtrs: PPointer; ItemCount: PtrUInt; Comparer: TListSortComparer_NoContext);
  26. procedure QuickSort_PtrList_Context(ItemPtrs: PPointer; ItemCount: PtrUInt; Comparer: TListSortComparer_Context; Context: Pointer);
  27. const
  28. QuickSort: TSortingAlgorithm = (
  29. PtrListSorter_NoContextComparer: @QuickSort_PtrList_NoContext;
  30. PtrListSorter_ContextComparer: @QuickSort_PtrList_Context
  31. );
  32. var
  33. DefaultSortingAlgorithm: PSortingAlgorithm = @QuickSort;
  34. implementation
  35. Procedure QuickSort_PtrList_NoContext(FList: PPointer; L, R : Longint;
  36. Compare: TListSortComparer_NoContext);
  37. var
  38. I, J : Longint;
  39. P, Q : Pointer;
  40. begin
  41. repeat
  42. I := L;
  43. J := R;
  44. P := FList[ (L + R) div 2 ];
  45. repeat
  46. while Compare(P, FList[i]) > 0 do
  47. I := I + 1;
  48. while Compare(P, FList[J]) < 0 do
  49. J := J - 1;
  50. If I <= J then
  51. begin
  52. Q := FList[I];
  53. Flist[I] := FList[J];
  54. FList[J] := Q;
  55. I := I + 1;
  56. J := J - 1;
  57. end;
  58. until I > J;
  59. // sort the smaller range recursively
  60. // sort the bigger range via the loop
  61. // Reasons: memory usage is O(log(n)) instead of O(n) and loop is faster than recursion
  62. if J - L < R - I then
  63. begin
  64. if L < J then
  65. QuickSort_PtrList_NoContext(FList, L, J, Compare);
  66. L := I;
  67. end
  68. else
  69. begin
  70. if I < R then
  71. QuickSort_PtrList_NoContext(FList, I, R, Compare);
  72. R := J;
  73. end;
  74. until L >= R;
  75. end;
  76. procedure QuickSort_PtrList_NoContext(ItemPtrs: PPointer; ItemCount: PtrUInt; Comparer: TListSortComparer_NoContext);
  77. begin
  78. if not Assigned(ItemPtrs) or (ItemCount < 2) then
  79. exit;
  80. QuickSort_PtrList_NoContext(ItemPtrs, 0, ItemCount - 1, Comparer);
  81. end;
  82. procedure QuickSort_PtrList_Context(ItemPtrs: PPointer; ItemCount: PtrUInt; Comparer: TListSortComparer_Context; Context: Pointer);
  83. Procedure QuickSort(L, R : Longint);
  84. var
  85. I, J : Longint;
  86. P, Q : Pointer;
  87. begin
  88. repeat
  89. I := L;
  90. J := R;
  91. P := ItemPtrs[ (L + R) div 2 ];
  92. repeat
  93. while Comparer(P, ItemPtrs[I], Context) > 0 do
  94. I := I + 1;
  95. while Comparer(P, ItemPtrs[J], Context) < 0 do
  96. J := J - 1;
  97. If I <= J then
  98. begin
  99. Q := ItemPtrs[I];
  100. ItemPtrs[I] := ItemPtrs[J];
  101. ItemPtrs[J] := Q;
  102. I := I + 1;
  103. J := J - 1;
  104. end;
  105. until I > J;
  106. // sort the smaller range recursively
  107. // sort the bigger range via the loop
  108. // Reasons: memory usage is O(log(n)) instead of O(n) and loop is faster than recursion
  109. if J - L < R - I then
  110. begin
  111. if L < J then
  112. QuickSort(L, J);
  113. L := I;
  114. end
  115. else
  116. begin
  117. if I < R then
  118. QuickSort(I, R);
  119. R := J;
  120. end;
  121. until L >= R;
  122. end;
  123. begin
  124. if not Assigned(ItemPtrs) or (ItemCount < 2) then
  125. exit;
  126. QuickSort(0, ItemCount - 1);
  127. end;
  128. end.