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.

279 lines
8.8 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: T;
  167. begin
  168. while (aLow < aHigh) do begin
  169. lo := aLow;
  170. hi := aHigh;
  171. p := aArray[(aLow + aHigh) div 2];
  172. repeat
  173. while (aComparer.Compare(p, aArray[lo]) > 0) and (lo < aHigh) do
  174. lo := lo + 1;
  175. while (aComparer.Compare(p, aArray[hi]) < 0) and (hi > aLow) do
  176. hi := hi - 1;
  177. if (lo <= hi) then begin
  178. aArray.Exchange(lo, hi);
  179. lo := lo + 1;
  180. hi := hi - 1;
  181. end;
  182. until (lo > hi);
  183. if (hi - aLow < aHigh - lo) then begin
  184. if (aLow < hi) then
  185. DoSort(aArray, aComparer, aLow, hi);
  186. aLow := lo;
  187. end else begin
  188. if (lo < aHigh) then
  189. DoSort(aArray, aComparer, lo, aHigh);
  190. aHigh := hi;
  191. end;
  192. end;
  193. end;
  194. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  195. class procedure TutlQuickSort.DoSort(
  196. constref aArray: PT;
  197. constref aComparer: IComparer;
  198. aLow: Integer;
  199. aHigh: Integer);
  200. var
  201. lo, hi: Integer;
  202. p, tmp: T;
  203. begin
  204. if not Assigned(aArray) then
  205. raise EArgumentNilException.Create('aArray');
  206. while (aLow < aHigh) do begin
  207. lo := aLow;
  208. hi := aHigh;
  209. p := aArray[(aLow + aHigh) div 2];
  210. repeat
  211. while (aComparer.Compare(p, aArray[lo]) > 0) and (lo < aHigh) do
  212. lo := lo + 1;
  213. while (aComparer.Compare(p, aArray[hi]) < 0) and (hi > aLow) do
  214. hi := hi - 1;
  215. if (lo <= hi) then begin
  216. tmp := aArray[lo];
  217. aArray[lo] := aArray[hi];
  218. aArray[hi] := tmp;
  219. lo := lo + 1;
  220. hi := hi - 1;
  221. end;
  222. until (lo > hi);
  223. if (hi - aLow < aHigh - lo) then begin
  224. if (aLow < hi) then
  225. DoSort(aArray, aComparer, aLow, hi);
  226. aLow := lo;
  227. end else begin
  228. if (lo < aHigh) then
  229. DoSort(aArray, aComparer, lo, aHigh);
  230. aHigh := hi;
  231. end;
  232. end;
  233. end;
  234. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  235. class procedure TutlQuickSort.Sort(
  236. constref aArray: IArray;
  237. constref aComparer: IComparer);
  238. begin
  239. if not Assigned(aComparer) then
  240. raise EArgumentNilException.Create('aComparer');
  241. DoSort(aArray, aComparer, 0, aArray.GetCount-1);
  242. end;
  243. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  244. class procedure TutlQuickSort.Sort(
  245. var aArray: T;
  246. constref aCount: Integer;
  247. constref aComparer: IComparer);
  248. begin
  249. if not Assigned(aComparer) then
  250. raise EArgumentNilException.Create('aComparer');
  251. DoSort(@aArray, aComparer, 0, aCount-1);
  252. end;
  253. end.