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.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. if (aMin <= aMax) then begin
  91. i := aMin + Trunc((aMax - aMin) / 2);
  92. cmp := aComparer.Compare(aItem, aArray[i]);
  93. if (cmp = 0) then begin
  94. result := true;
  95. aIndex := i;
  96. end else if (cmp < 0) then
  97. result := DoSearch(aArray, aComparer, aMin, i-1, aItem, aIndex)
  98. else if (cmp > 0) then
  99. result := DoSearch(aArray, aComparer, i+1, aMax, aItem, aIndex);
  100. end else begin
  101. result := false;
  102. aIndex := aMin;
  103. end;
  104. end;
  105. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  106. class function TutlBinarySearch.DoSearch(
  107. constref aArray: PT;
  108. constref aComparer: IComparer;
  109. const aMin: Integer;
  110. const aMax: Integer;
  111. constref aItem: T;
  112. out aIndex: Integer): Boolean;
  113. var
  114. i, cmp: Integer;
  115. begin
  116. if (aMin <= aMax) then begin
  117. i := aMin + Trunc((aMax - aMin) / 2);
  118. cmp := aComparer.Compare(aItem, aArray[i]);
  119. if (cmp = 0) then begin
  120. result := true;
  121. aIndex := i;
  122. end else if (cmp < 0) then
  123. result := DoSearch(aArray, aComparer, aMin, i-1, aItem, aIndex)
  124. else if (cmp > 0) then
  125. result := DoSearch(aArray, aComparer, i+1, aMax, aItem, aIndex);
  126. end else begin
  127. result := false;
  128. aIndex := aMin;
  129. end;
  130. end;
  131. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  132. class function TutlBinarySearch.Search(
  133. constref aArray: IReadOnlyArray;
  134. constref aComparer: IComparer;
  135. constref aItem: T;
  136. out aIndex: Integer): Boolean;
  137. begin
  138. if not Assigned(aComparer) then
  139. raise EArgumentNilException.Create('aComparer');
  140. result := DoSearch(aArray, aComparer, 0, aArray.Count-1, aItem, aIndex);
  141. end;
  142. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  143. class function TutlBinarySearch.Search(
  144. const aArray;
  145. const aCount: Integer;
  146. constref aComparer: IComparer;
  147. constref aItem: T;
  148. out aIndex: Integer): Boolean;
  149. begin
  150. if not Assigned(aComparer) then
  151. raise EArgumentNilException.Create('aComparer');
  152. result := DoSearch(@aArray, aComparer, 0, aCount-1, aItem, aIndex);
  153. end;
  154. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  155. //TutlQuickSort/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  156. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  157. class procedure TutlQuickSort.DoSort(
  158. constref aArray: IArray;
  159. constref aComparer: IComparer;
  160. aLow: Integer;
  161. aHigh: Integer);
  162. var
  163. lo, hi: Integer;
  164. p, tmp: T;
  165. begin
  166. repeat
  167. lo := aLow;
  168. hi := aHigh;
  169. p := aArray[(aLow + aHigh) div 2];
  170. repeat
  171. while (aComparer.Compare(p, aArray[lo]) > 0) do
  172. lo := lo + 1;
  173. while (aComparer.Compare(p, aArray[hi]) < 0) do
  174. hi := hi - 1;
  175. if (lo <= hi) then begin
  176. tmp := aArray[lo];
  177. aArray[lo] := aArray[hi];
  178. aArray[hi] := tmp;
  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. until (aLow >= aHigh);
  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. repeat
  207. lo := aLow;
  208. hi := aHigh;
  209. p := aArray[(aLow + aHigh) div 2];
  210. repeat
  211. while (aComparer.Compare(p, aArray[lo]) > 0) do
  212. lo := lo + 1;
  213. while (aComparer.Compare(p, aArray[hi]) < 0) 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. until (aLow >= aHigh);
  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.