You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

281 lines
8.7 KiB

  1. unit uutlAlgorithm;
  2. {$mode objfpc}{$H+}
  3. interface
  4. uses
  5. Classes, SysUtils,
  6. uutlInterfaces;
  7. type
  8. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  9. generic TutlBinarySearch<T> = class
  10. public type
  11. IReadOnlyArray = specialize IutlReadOnlyArray<T>;
  12. IComparer = specialize IutlComparer<T>;
  13. PT = ^T;
  14. private
  15. class function DoSearch(
  16. constref aArray: IReadOnlyArray;
  17. constref aComparer: IComparer;
  18. const aMin: Integer;
  19. const aMax: Integer;
  20. constref aItem: T;
  21. out aIndex: Integer): Boolean;
  22. class function DoSearch(
  23. constref aArray: PT;
  24. constref aComparer: IComparer;
  25. const aMin: Integer;
  26. const aMax: Integer;
  27. constref aItem: T;
  28. out aIndex: Integer): Boolean;
  29. public
  30. // search aItem in aArray using aComparer
  31. // aList needs to bee sorted
  32. // aIndex is the index the item was found or should be inserted
  33. // returns TRUE when found, FALSE otherwise
  34. class function Search(
  35. constref aArray: IReadOnlyArray;
  36. constref aComparer: IComparer;
  37. constref aItem: T;
  38. out aIndex: Integer): Boolean; overload;
  39. // search aItem in aList using aComparer
  40. // aList needs to bee sorted
  41. // aIndex is the index the item was found or should be inserted
  42. // returns TRUE when found, FALSE otherwise
  43. class function Search(
  44. const aArray;
  45. const aCount: Integer;
  46. constref aComparer: IComparer;
  47. constref aItem: T;
  48. out aIndex: Integer): Boolean; overload;
  49. end;
  50. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  51. generic TutlQuickSort<T> = class
  52. public type
  53. IArray = specialize IutlArray<T>;
  54. IComparer = specialize IutlComparer<T>;
  55. PT = ^T;
  56. private
  57. class procedure DoSort(
  58. constref aArray: IArray;
  59. constref aComparer: IComparer;
  60. aLow: Integer;
  61. aHigh: Integer); overload;
  62. class procedure DoSort(
  63. constref aArray: PT;
  64. constref aComparer: IComparer;
  65. aLow: Integer;
  66. aHigh: Integer); overload;
  67. public
  68. class procedure Sort(
  69. constref aArray: IArray;
  70. constref aComparer: IComparer); overload;
  71. class procedure Sort(
  72. var aArray: T;
  73. constref aCount: Integer;
  74. constref aComparer: IComparer); overload;
  75. end;
  76. implementation
  77. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  78. //TutlBinarySearch//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  79. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  80. class function TutlBinarySearch.DoSearch(
  81. constref aArray: IReadOnlyArray;
  82. constref aComparer: IComparer;
  83. const aMin: Integer;
  84. const aMax: Integer;
  85. constref aItem: T;
  86. out aIndex: Integer): Boolean;
  87. var
  88. i, cmp: Integer;
  89. begin
  90. result := false;
  91. if (aMin <= aMax) then begin
  92. i := aMin + Trunc((aMax - aMin) / 2);
  93. cmp := aComparer.Compare(aItem, aArray[i]);
  94. if (cmp = 0) then begin
  95. result := true;
  96. aIndex := i;
  97. end else if (cmp < 0) then
  98. result := DoSearch(aArray, aComparer, aMin, i-1, aItem, aIndex)
  99. else if (cmp > 0) then
  100. result := DoSearch(aArray, aComparer, i+1, aMax, aItem, aIndex);
  101. end else begin
  102. result := false;
  103. aIndex := aMin;
  104. end;
  105. end;
  106. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  107. class function TutlBinarySearch.DoSearch(
  108. constref aArray: PT;
  109. constref aComparer: IComparer;
  110. const aMin: Integer;
  111. const aMax: Integer;
  112. constref aItem: T;
  113. out aIndex: Integer): Boolean;
  114. var
  115. i, cmp: Integer;
  116. begin
  117. result := false;
  118. if (aMin <= aMax) then begin
  119. i := aMin + Trunc((aMax - aMin) / 2);
  120. cmp := aComparer.Compare(aItem, aArray[i]);
  121. if (cmp = 0) then begin
  122. result := true;
  123. aIndex := i;
  124. end else if (cmp < 0) then
  125. result := DoSearch(aArray, aComparer, aMin, i-1, aItem, aIndex)
  126. else if (cmp > 0) then
  127. result := DoSearch(aArray, aComparer, i+1, aMax, aItem, aIndex);
  128. end else begin
  129. result := false;
  130. aIndex := aMin;
  131. end;
  132. end;
  133. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  134. class function TutlBinarySearch.Search(
  135. constref aArray: IReadOnlyArray;
  136. constref aComparer: IComparer;
  137. constref aItem: T;
  138. out aIndex: Integer): Boolean;
  139. begin
  140. if not Assigned(aComparer) then
  141. raise EArgumentNilException.Create('aComparer');
  142. result := DoSearch(aArray, aComparer, 0, aArray.Count-1, aItem, aIndex);
  143. end;
  144. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  145. class function TutlBinarySearch.Search(
  146. const aArray;
  147. const aCount: Integer;
  148. constref aComparer: IComparer;
  149. constref aItem: T;
  150. out aIndex: Integer): Boolean;
  151. begin
  152. if not Assigned(aComparer) then
  153. raise EArgumentNilException.Create('aComparer');
  154. result := DoSearch(@aArray, aComparer, 0, aCount-1, aItem, aIndex);
  155. end;
  156. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  157. //TutlQuickSort/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  158. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  159. class procedure TutlQuickSort.DoSort(
  160. constref aArray: IArray;
  161. constref aComparer: IComparer;
  162. aLow: Integer;
  163. aHigh: Integer);
  164. var
  165. lo, hi: Integer;
  166. p, tmp: T;
  167. begin
  168. repeat
  169. lo := aLow;
  170. hi := aHigh;
  171. p := aArray[(aLow + aHigh) div 2];
  172. repeat
  173. while (aComparer.Compare(p, aArray[lo]) > 0) do
  174. lo := lo + 1;
  175. while (aComparer.Compare(p, aArray[hi]) < 0) do
  176. hi := hi - 1;
  177. if (lo <= hi) then begin
  178. tmp := aArray[lo];
  179. aArray[lo] := aArray[hi];
  180. aArray[hi] := tmp;
  181. lo := lo + 1;
  182. hi := hi - 1;
  183. end;
  184. until (lo > hi);
  185. if (hi - aLow < aHigh - lo) then begin
  186. if (aLow < hi) then
  187. DoSort(aArray, aComparer, aLow, hi);
  188. aLow := lo;
  189. end else begin
  190. if (lo < aHigh) then
  191. DoSort(aArray, aComparer, lo, aHigh);
  192. aHigh := hi;
  193. end;
  194. until (aLow >= aHigh);
  195. end;
  196. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  197. class procedure TutlQuickSort.DoSort(
  198. constref aArray: PT;
  199. constref aComparer: IComparer;
  200. aLow: Integer;
  201. aHigh: Integer);
  202. var
  203. lo, hi: Integer;
  204. p, tmp: T;
  205. begin
  206. if not Assigned(aArray) then
  207. raise EArgumentNilException.Create('aArray');
  208. repeat
  209. lo := aLow;
  210. hi := aHigh;
  211. p := aArray[(aLow + aHigh) div 2];
  212. repeat
  213. while (aComparer.Compare(p, aArray[lo]) > 0) do
  214. lo := lo + 1;
  215. while (aComparer.Compare(p, aArray[hi]) < 0) do
  216. hi := hi - 1;
  217. if (lo <= hi) then begin
  218. tmp := aArray[lo];
  219. aArray[lo] := aArray[hi];
  220. aArray[hi] := tmp;
  221. lo := lo + 1;
  222. hi := hi - 1;
  223. end;
  224. until (lo > hi);
  225. if (hi - aLow < aHigh - lo) then begin
  226. if (aLow < hi) then
  227. DoSort(aArray, aComparer, aLow, hi);
  228. aLow := lo;
  229. end else begin
  230. if (lo < aHigh) then
  231. DoSort(aArray, aComparer, lo, aHigh);
  232. aHigh := hi;
  233. end;
  234. until (aLow >= aHigh);
  235. end;
  236. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  237. class procedure TutlQuickSort.Sort(
  238. constref aArray: IArray;
  239. constref aComparer: IComparer);
  240. begin
  241. if not Assigned(aComparer) then
  242. raise EArgumentNilException.Create('aComparer');
  243. DoSort(aArray, aComparer, 0, aArray.GetCount-1);
  244. end;
  245. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  246. class procedure TutlQuickSort.Sort(
  247. var aArray: T;
  248. constref aCount: Integer;
  249. constref aComparer: IComparer);
  250. begin
  251. if not Assigned(aComparer) then
  252. raise EArgumentNilException.Create('aComparer');
  253. DoSort(@aArray, aComparer, 0, aCount-1);
  254. end;
  255. end.