avl_tree.pp 31 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180
  1. {
  2. ***************************************************************************
  3. * *
  4. * This source is free software; you can redistribute it and/or modify *
  5. * it under the terms of the GNU General Public License as published by *
  6. * the Free Software Foundation; either version 2 of the License, or *
  7. * (at your option) any later version. *
  8. * *
  9. * This code is distributed in the hope that it will be useful, but *
  10. * WITHOUT ANY WARRANTY; without even the implied warranty of *
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
  12. * General Public License for more details. *
  13. * *
  14. * A copy of the GNU General Public License is available on the World *
  15. * Wide Web at <http://www.gnu.org/copyleft/gpl.html>. You can also *
  16. * obtain it by writing to the Free Software Foundation, *
  17. * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
  18. * *
  19. ***************************************************************************
  20. Author: Mattias Gaertner
  21. Abstract:
  22. TAVLTree is an Average Level binary Tree. This binary tree is always
  23. balanced, so that inserting, deleting and finding a node is performed in
  24. O(log(#Nodes)).
  25. }
  26. unit AVL_Tree;
  27. {$ifdef FPC}{$mode objfpc}{$endif}{$H+}
  28. interface
  29. {off $DEFINE MEM_CHECK}
  30. uses
  31. {$IFDEF MEM_CHECK}MemCheck,{$ENDIF}
  32. Classes, SysUtils;
  33. type
  34. TAVLTreeNode = class
  35. public
  36. Parent, Left, Right: TAVLTreeNode;
  37. Balance: integer;
  38. Data: Pointer;
  39. procedure Clear;
  40. function TreeDepth: integer; // longest WAY down. e.g. only one node => 0 !
  41. constructor Create;
  42. destructor Destroy; override;
  43. end;
  44. TAVLTree = class
  45. private
  46. FOnCompare: TListSortCompare;
  47. FCount: integer;
  48. procedure BalanceAfterInsert(ANode: TAVLTreeNode);
  49. procedure BalanceAfterDelete(ANode: TAVLTreeNode);
  50. function FindInsertPos(Data: Pointer): TAVLTreeNode;
  51. procedure SetOnCompare(const AValue: TListSortCompare);
  52. public
  53. Root: TAVLTreeNode;
  54. function Find(Data: Pointer): TAVLTreeNode;
  55. function FindKey(Key: Pointer;
  56. OnCompareKeyWithData: TListSortCompare): TAVLTreeNode;
  57. function FindSuccessor(ANode: TAVLTreeNode): TAVLTreeNode;
  58. function FindPrecessor(ANode: TAVLTreeNode): TAVLTreeNode;
  59. function FindLowest: TAVLTreeNode;
  60. function FindHighest: TAVLTreeNode;
  61. function FindNearest(Data: Pointer): TAVLTreeNode;
  62. function FindPointer(Data: Pointer): TAVLTreeNode;
  63. function FindLeftMost(Data: Pointer): TAVLTreeNode;
  64. function FindRightMost(Data: Pointer): TAVLTreeNode;
  65. function FindLeftMostKey(Key: Pointer;
  66. OnCompareKeyWithData: TListSortCompare): TAVLTreeNode;
  67. function FindRightMostKey(Key: Pointer;
  68. OnCompareKeyWithData: TListSortCompare): TAVLTreeNode;
  69. function FindLeftMostSameKey(ANode: TAVLTreeNode): TAVLTreeNode;
  70. function FindRightMostSameKey(ANode: TAVLTreeNode): TAVLTreeNode;
  71. procedure Add(ANode: TAVLTreeNode);
  72. function Add(Data: Pointer): TAVLTreeNode;
  73. procedure Delete(ANode: TAVLTreeNode);
  74. procedure Remove(Data: Pointer);
  75. procedure RemovePointer(Data: Pointer);
  76. procedure MoveDataLeftMost(var ANode: TAVLTreeNode);
  77. procedure MoveDataRightMost(var ANode: TAVLTreeNode);
  78. property OnCompare: TListSortCompare read FOnCompare write SetOnCompare;
  79. procedure Clear;
  80. procedure FreeAndClear;
  81. procedure FreeAndDelete(ANode: TAVLTreeNode);
  82. property Count: integer read FCount;
  83. function ConsistencyCheck: integer;
  84. procedure WriteReportToStream(s: TStream; var StreamSize: int64);
  85. function ReportAsString: string;
  86. constructor Create(OnCompareMethod: TListSortCompare);
  87. constructor Create;
  88. destructor Destroy; override;
  89. end;
  90. TAVLTreeNodeMemManager = class
  91. private
  92. FFirstFree: TAVLTreeNode;
  93. FFreeCount: integer;
  94. FCount: integer;
  95. FMinFree: integer;
  96. FMaxFreeRatio: integer;
  97. procedure SetMaxFreeRatio(NewValue: integer);
  98. procedure SetMinFree(NewValue: integer);
  99. procedure DisposeFirstFreeNode;
  100. public
  101. procedure DisposeNode(ANode: TAVLTreeNode);
  102. function NewNode: TAVLTreeNode;
  103. property MinimumFreeNode: integer read FMinFree write SetMinFree;
  104. property MaximumFreeNodeRatio: integer
  105. read FMaxFreeRatio write SetMaxFreeRatio; // in one eighth steps
  106. property Count: integer read FCount;
  107. procedure Clear;
  108. constructor Create;
  109. destructor Destroy; override;
  110. end;
  111. implementation
  112. var NodeMemManager: TAVLTreeNodeMemManager;
  113. function ComparePointer(Data1, Data2: Pointer): integer;
  114. begin
  115. if Data1>Data2 then Result:=-1
  116. else if Data1<Data2 then Result:=1
  117. else Result:=0;
  118. end;
  119. { TAVLTree }
  120. function TAVLTree.Add(Data: Pointer): TAVLTreeNode;
  121. begin
  122. Result:=NodeMemManager.NewNode;
  123. Result.Data:=Data;
  124. Add(Result);
  125. end;
  126. procedure TAVLTree.Add(ANode: TAVLTreeNode);
  127. // add a node. If there are already nodes with the same value it will be
  128. // inserted rightmost
  129. var InsertPos: TAVLTreeNode;
  130. InsertComp: integer;
  131. begin
  132. ANode.Left:=nil;
  133. ANode.Right:=nil;
  134. inc(FCount);
  135. if Root<>nil then begin
  136. InsertPos:=FindInsertPos(ANode.Data);
  137. InsertComp:=fOnCompare(ANode.Data,InsertPos.Data);
  138. ANode.Parent:=InsertPos;
  139. if InsertComp<0 then begin
  140. // insert to the left
  141. InsertPos.Left:=ANode;
  142. end else begin
  143. // insert to the right
  144. InsertPos.Right:=ANode;
  145. end;
  146. BalanceAfterInsert(ANode);
  147. end else begin
  148. Root:=ANode;
  149. ANode.Parent:=nil;
  150. end;
  151. end;
  152. function TAVLTree.FindLowest: TAVLTreeNode;
  153. begin
  154. Result:=Root;
  155. if Result<>nil then
  156. while Result.Left<>nil do Result:=Result.Left;
  157. end;
  158. function TAVLTree.FindHighest: TAVLTreeNode;
  159. begin
  160. Result:=Root;
  161. if Result<>nil then
  162. while Result.Right<>nil do Result:=Result.Right;
  163. end;
  164. procedure TAVLTree.BalanceAfterDelete(ANode: TAVLTreeNode);
  165. var OldParent, OldRight, OldRightLeft, OldLeft, OldLeftRight,
  166. OldRightLeftLeft, OldRightLeftRight, OldLeftRightLeft, OldLeftRightRight
  167. : TAVLTreeNode;
  168. begin
  169. if (ANode=nil) then exit;
  170. if ((ANode.Balance=+1) or (ANode.Balance=-1)) then exit;
  171. OldParent:=ANode.Parent;
  172. if (ANode.Balance=0) then begin
  173. // Treeheight has decreased by one
  174. if (OldParent<>nil) then begin
  175. if(OldParent.Left=ANode) then
  176. Inc(OldParent.Balance)
  177. else
  178. Dec(OldParent.Balance);
  179. BalanceAfterDelete(OldParent);
  180. end;
  181. exit;
  182. end;
  183. if (ANode.Balance=+2) then begin
  184. // Node is overweighted to the right
  185. OldRight:=ANode.Right;
  186. if (OldRight.Balance>=0) then begin
  187. // OldRight.Balance=={0 or -1}
  188. // rotate left
  189. OldRightLeft:=OldRight.Left;
  190. if (OldParent<>nil) then begin
  191. if (OldParent.Left=ANode) then
  192. OldParent.Left:=OldRight
  193. else
  194. OldParent.Right:=OldRight;
  195. end else
  196. Root:=OldRight;
  197. ANode.Parent:=OldRight;
  198. ANode.Right:=OldRightLeft;
  199. OldRight.Parent:=OldParent;
  200. OldRight.Left:=ANode;
  201. if (OldRightLeft<>nil) then
  202. OldRightLeft.Parent:=ANode;
  203. ANode.Balance:=(1-OldRight.Balance);
  204. Dec(OldRight.Balance);
  205. BalanceAfterDelete(OldRight);
  206. end else begin
  207. // OldRight.Balance=-1
  208. // double rotate right left
  209. OldRightLeft:=OldRight.Left;
  210. OldRightLeftLeft:=OldRightLeft.Left;
  211. OldRightLeftRight:=OldRightLeft.Right;
  212. if (OldParent<>nil) then begin
  213. if (OldParent.Left=ANode) then
  214. OldParent.Left:=OldRightLeft
  215. else
  216. OldParent.Right:=OldRightLeft;
  217. end else
  218. Root:=OldRightLeft;
  219. ANode.Parent:=OldRightLeft;
  220. ANode.Right:=OldRightLeftLeft;
  221. OldRight.Parent:=OldRightLeft;
  222. OldRight.Left:=OldRightLeftRight;
  223. OldRightLeft.Parent:=OldParent;
  224. OldRightLeft.Left:=ANode;
  225. OldRightLeft.Right:=OldRight;
  226. if (OldRightLeftLeft<>nil) then
  227. OldRightLeftLeft.Parent:=ANode;
  228. if (OldRightLeftRight<>nil) then
  229. OldRightLeftRight.Parent:=OldRight;
  230. if (OldRightLeft.Balance<=0) then
  231. ANode.Balance:=0
  232. else
  233. ANode.Balance:=-1;
  234. if (OldRightLeft.Balance>=0) then
  235. OldRight.Balance:=0
  236. else
  237. OldRight.Balance:=+1;
  238. OldRightLeft.Balance:=0;
  239. BalanceAfterDelete(OldRightLeft);
  240. end;
  241. end else begin
  242. // Node.Balance=-2
  243. // Node is overweighted to the left
  244. OldLeft:=ANode.Left;
  245. if (OldLeft.Balance<=0) then begin
  246. // rotate right
  247. OldLeftRight:=OldLeft.Right;
  248. if (OldParent<>nil) then begin
  249. if (OldParent.Left=ANode) then
  250. OldParent.Left:=OldLeft
  251. else
  252. OldParent.Right:=OldLeft;
  253. end else
  254. Root:=OldLeft;
  255. ANode.Parent:=OldLeft;
  256. ANode.Left:=OldLeftRight;
  257. OldLeft.Parent:=OldParent;
  258. OldLeft.Right:=ANode;
  259. if (OldLeftRight<>nil) then
  260. OldLeftRight.Parent:=ANode;
  261. ANode.Balance:=(-1-OldLeft.Balance);
  262. Inc(OldLeft.Balance);
  263. BalanceAfterDelete(OldLeft);
  264. end else begin
  265. // OldLeft.Balance = 1
  266. // double rotate left right
  267. OldLeftRight:=OldLeft.Right;
  268. OldLeftRightLeft:=OldLeftRight.Left;
  269. OldLeftRightRight:=OldLeftRight.Right;
  270. if (OldParent<>nil) then begin
  271. if (OldParent.Left=ANode) then
  272. OldParent.Left:=OldLeftRight
  273. else
  274. OldParent.Right:=OldLeftRight;
  275. end else
  276. Root:=OldLeftRight;
  277. ANode.Parent:=OldLeftRight;
  278. ANode.Left:=OldLeftRightRight;
  279. OldLeft.Parent:=OldLeftRight;
  280. OldLeft.Right:=OldLeftRightLeft;
  281. OldLeftRight.Parent:=OldParent;
  282. OldLeftRight.Left:=OldLeft;
  283. OldLeftRight.Right:=ANode;
  284. if (OldLeftRightLeft<>nil) then
  285. OldLeftRightLeft.Parent:=OldLeft;
  286. if (OldLeftRightRight<>nil) then
  287. OldLeftRightRight.Parent:=ANode;
  288. if (OldLeftRight.Balance>=0) then
  289. ANode.Balance:=0
  290. else
  291. ANode.Balance:=+1;
  292. if (OldLeftRight.Balance<=0) then
  293. OldLeft.Balance:=0
  294. else
  295. OldLeft.Balance:=-1;
  296. OldLeftRight.Balance:=0;
  297. BalanceAfterDelete(OldLeftRight);
  298. end;
  299. end;
  300. end;
  301. procedure TAVLTree.BalanceAfterInsert(ANode: TAVLTreeNode);
  302. var OldParent, OldParentParent, OldRight, OldRightLeft, OldRightRight, OldLeft,
  303. OldLeftLeft, OldLeftRight: TAVLTreeNode;
  304. begin
  305. OldParent:=ANode.Parent;
  306. if (OldParent=nil) then exit;
  307. if (OldParent.Left=ANode) then begin
  308. // Node is left son
  309. dec(OldParent.Balance);
  310. if (OldParent.Balance=0) then exit;
  311. if (OldParent.Balance=-1) then begin
  312. BalanceAfterInsert(OldParent);
  313. exit;
  314. end;
  315. // OldParent.Balance=-2
  316. if (ANode.Balance=-1) then begin
  317. // rotate
  318. OldRight:=ANode.Right;
  319. OldParentParent:=OldParent.Parent;
  320. if (OldParentParent<>nil) then begin
  321. // OldParent has GrandParent. GrandParent gets new child
  322. if (OldParentParent.Left=OldParent) then
  323. OldParentParent.Left:=ANode
  324. else
  325. OldParentParent.Right:=ANode;
  326. end else begin
  327. // OldParent was root node. New root node
  328. Root:=ANode;
  329. end;
  330. ANode.Parent:=OldParentParent;
  331. ANode.Right:=OldParent;
  332. OldParent.Parent:=ANode;
  333. OldParent.Left:=OldRight;
  334. if (OldRight<>nil) then
  335. OldRight.Parent:=OldParent;
  336. ANode.Balance:=0;
  337. OldParent.Balance:=0;
  338. end else begin
  339. // Node.Balance = +1
  340. // double rotate
  341. OldParentParent:=OldParent.Parent;
  342. OldRight:=ANode.Right;
  343. OldRightLeft:=OldRight.Left;
  344. OldRightRight:=OldRight.Right;
  345. if (OldParentParent<>nil) then begin
  346. // OldParent has GrandParent. GrandParent gets new child
  347. if (OldParentParent.Left=OldParent) then
  348. OldParentParent.Left:=OldRight
  349. else
  350. OldParentParent.Right:=OldRight;
  351. end else begin
  352. // OldParent was root node. new root node
  353. Root:=OldRight;
  354. end;
  355. OldRight.Parent:=OldParentParent;
  356. OldRight.Left:=ANode;
  357. OldRight.Right:=OldParent;
  358. ANode.Parent:=OldRight;
  359. ANode.Right:=OldRightLeft;
  360. OldParent.Parent:=OldRight;
  361. OldParent.Left:=OldRightRight;
  362. if (OldRightLeft<>nil) then
  363. OldRightLeft.Parent:=ANode;
  364. if (OldRightRight<>nil) then
  365. OldRightRight.Parent:=OldParent;
  366. if (OldRight.Balance<=0) then
  367. ANode.Balance:=0
  368. else
  369. ANode.Balance:=-1;
  370. if (OldRight.Balance=-1) then
  371. OldParent.Balance:=1
  372. else
  373. OldParent.Balance:=0;
  374. OldRight.Balance:=0;
  375. end;
  376. end else begin
  377. // Node is right son
  378. Inc(OldParent.Balance);
  379. if (OldParent.Balance=0) then exit;
  380. if (OldParent.Balance=+1) then begin
  381. BalanceAfterInsert(OldParent);
  382. exit;
  383. end;
  384. // OldParent.Balance = +2
  385. if(ANode.Balance=+1) then begin
  386. // rotate
  387. OldLeft:=ANode.Left;
  388. OldParentParent:=OldParent.Parent;
  389. if (OldParentParent<>nil) then begin
  390. // Parent has GrandParent . GrandParent gets new child
  391. if(OldParentParent.Left=OldParent) then
  392. OldParentParent.Left:=ANode
  393. else
  394. OldParentParent.Right:=ANode;
  395. end else begin
  396. // OldParent was root node . new root node
  397. Root:=ANode;
  398. end;
  399. ANode.Parent:=OldParentParent;
  400. ANode.Left:=OldParent;
  401. OldParent.Parent:=ANode;
  402. OldParent.Right:=OldLeft;
  403. if (OldLeft<>nil) then
  404. OldLeft.Parent:=OldParent;
  405. ANode.Balance:=0;
  406. OldParent.Balance:=0;
  407. end else begin
  408. // Node.Balance = -1
  409. // double rotate
  410. OldLeft:=ANode.Left;
  411. OldParentParent:=OldParent.Parent;
  412. OldLeftLeft:=OldLeft.Left;
  413. OldLeftRight:=OldLeft.Right;
  414. if (OldParentParent<>nil) then begin
  415. // OldParent has GrandParent . GrandParent gets new child
  416. if (OldParentParent.Left=OldParent) then
  417. OldParentParent.Left:=OldLeft
  418. else
  419. OldParentParent.Right:=OldLeft;
  420. end else begin
  421. // OldParent was root node . new root node
  422. Root:=OldLeft;
  423. end;
  424. OldLeft.Parent:=OldParentParent;
  425. OldLeft.Left:=OldParent;
  426. OldLeft.Right:=ANode;
  427. ANode.Parent:=OldLeft;
  428. ANode.Left:=OldLeftRight;
  429. OldParent.Parent:=OldLeft;
  430. OldParent.Right:=OldLeftLeft;
  431. if (OldLeftLeft<>nil) then
  432. OldLeftLeft.Parent:=OldParent;
  433. if (OldLeftRight<>nil) then
  434. OldLeftRight.Parent:=ANode;
  435. if (OldLeft.Balance>=0) then
  436. ANode.Balance:=0
  437. else
  438. ANode.Balance:=+1;
  439. if (OldLeft.Balance=+1) then
  440. OldParent.Balance:=-1
  441. else
  442. OldParent.Balance:=0;
  443. OldLeft.Balance:=0;
  444. end;
  445. end;
  446. end;
  447. procedure TAVLTree.Clear;
  448. procedure DeleteNode(ANode: TAVLTreeNode);
  449. begin
  450. if ANode<>nil then begin
  451. if ANode.Left<>nil then DeleteNode(ANode.Left);
  452. if ANode.Right<>nil then DeleteNode(ANode.Right);
  453. end;
  454. NodeMemManager.DisposeNode(ANode);
  455. end;
  456. // Clear
  457. begin
  458. DeleteNode(Root);
  459. Root:=nil;
  460. FCount:=0;
  461. end;
  462. constructor TAVLTree.Create(OnCompareMethod: TListSortCompare);
  463. begin
  464. inherited Create;
  465. FOnCompare:=OnCompareMethod;
  466. FCount:=0;
  467. end;
  468. constructor TAVLTree.Create;
  469. begin
  470. Create(@ComparePointer);
  471. end;
  472. procedure TAVLTree.Delete(ANode: TAVLTreeNode);
  473. var OldParent, OldLeft, OldRight, Successor, OldSuccParent, OldSuccLeft,
  474. OldSuccRight: TAVLTreeNode;
  475. OldBalance: integer;
  476. begin
  477. OldParent:=ANode.Parent;
  478. OldBalance:=ANode.Balance;
  479. ANode.Parent:=nil;
  480. ANode.Balance:=0;
  481. if ((ANode.Left=nil) and (ANode.Right=nil)) then begin
  482. // Node is Leaf (no children)
  483. if (OldParent<>nil) then begin
  484. // Node has parent
  485. if (OldParent.Left=ANode) then begin
  486. // Node is left Son of OldParent
  487. OldParent.Left:=nil;
  488. Inc(OldParent.Balance);
  489. end else begin
  490. // Node is right Son of OldParent
  491. OldParent.Right:=nil;
  492. Dec(OldParent.Balance);
  493. end;
  494. BalanceAfterDelete(OldParent);
  495. end else begin
  496. // Node is the only node of tree
  497. Root:=nil;
  498. end;
  499. dec(FCount);
  500. NodeMemManager.DisposeNode(ANode);
  501. exit;
  502. end;
  503. if (ANode.Right=nil) then begin
  504. // Left is only son
  505. // and because DelNode is AVL, Right has no childrens
  506. // replace DelNode with Left
  507. OldLeft:=ANode.Left;
  508. ANode.Left:=nil;
  509. OldLeft.Parent:=OldParent;
  510. if (OldParent<>nil) then begin
  511. if (OldParent.Left=ANode) then begin
  512. OldParent.Left:=OldLeft;
  513. Inc(OldParent.Balance);
  514. end else begin
  515. OldParent.Right:=OldLeft;
  516. Dec(OldParent.Balance);
  517. end;
  518. BalanceAfterDelete(OldParent);
  519. end else begin
  520. Root:=OldLeft;
  521. end;
  522. dec(FCount);
  523. NodeMemManager.DisposeNode(ANode);
  524. exit;
  525. end;
  526. if (ANode.Left=nil) then begin
  527. // Right is only son
  528. // and because DelNode is AVL, Left has no childrens
  529. // replace DelNode with Right
  530. OldRight:=ANode.Right;
  531. ANode.Right:=nil;
  532. OldRight.Parent:=OldParent;
  533. if (OldParent<>nil) then begin
  534. if (OldParent.Left=ANode) then begin
  535. OldParent.Left:=OldRight;
  536. Inc(OldParent.Balance);
  537. end else begin
  538. OldParent.Right:=OldRight;
  539. Dec(OldParent.Balance);
  540. end;
  541. BalanceAfterDelete(OldParent);
  542. end else begin
  543. Root:=OldRight;
  544. end;
  545. dec(FCount);
  546. NodeMemManager.DisposeNode(ANode);
  547. exit;
  548. end;
  549. // DelNode has both: Left and Right
  550. // Replace ANode with symmetric Successor
  551. Successor:=FindSuccessor(ANode);
  552. OldLeft:=ANode.Left;
  553. OldRight:=ANode.Right;
  554. OldSuccParent:=Successor.Parent;
  555. OldSuccLeft:=Successor.Left;
  556. OldSuccRight:=Successor.Right;
  557. ANode.Balance:=Successor.Balance;
  558. Successor.Balance:=OldBalance;
  559. if (OldSuccParent<>ANode) then begin
  560. // at least one node between ANode and Successor
  561. ANode.Parent:=Successor.Parent;
  562. if (OldSuccParent.Left=Successor) then
  563. OldSuccParent.Left:=ANode
  564. else
  565. OldSuccParent.Right:=ANode;
  566. Successor.Right:=OldRight;
  567. OldRight.Parent:=Successor;
  568. end else begin
  569. // Successor is right son of ANode
  570. ANode.Parent:=Successor;
  571. Successor.Right:=ANode;
  572. end;
  573. Successor.Left:=OldLeft;
  574. if OldLeft<>nil then
  575. OldLeft.Parent:=Successor;
  576. Successor.Parent:=OldParent;
  577. ANode.Left:=OldSuccLeft;
  578. if ANode.Left<>nil then
  579. ANode.Left.Parent:=ANode;
  580. ANode.Right:=OldSuccRight;
  581. if ANode.Right<>nil then
  582. ANode.Right.Parent:=ANode;
  583. if (OldParent<>nil) then begin
  584. if (OldParent.Left=ANode) then
  585. OldParent.Left:=Successor
  586. else
  587. OldParent.Right:=Successor;
  588. end else
  589. Root:=Successor;
  590. // delete Node as usual
  591. Delete(ANode);
  592. end;
  593. procedure TAVLTree.Remove(Data: Pointer);
  594. var ANode: TAVLTreeNode;
  595. begin
  596. ANode:=Find(Data);
  597. if ANode<>nil then
  598. Delete(ANode);
  599. end;
  600. procedure TAVLTree.RemovePointer(Data: Pointer);
  601. var
  602. ANode: TAVLTreeNode;
  603. begin
  604. ANode:=FindPointer(Data);
  605. if ANode<>nil then
  606. Delete(ANode);
  607. end;
  608. destructor TAVLTree.Destroy;
  609. begin
  610. Clear;
  611. inherited Destroy;
  612. end;
  613. function TAVLTree.Find(Data: Pointer): TAVLTreeNode;
  614. var Comp: integer;
  615. begin
  616. Result:=Root;
  617. while (Result<>nil) do begin
  618. Comp:=fOnCompare(Data,Result.Data);
  619. if Comp=0 then exit;
  620. if Comp<0 then begin
  621. Result:=Result.Left
  622. end else begin
  623. Result:=Result.Right
  624. end;
  625. end;
  626. end;
  627. function TAVLTree.FindKey(Key: Pointer; OnCompareKeyWithData: TListSortCompare
  628. ): TAVLTreeNode;
  629. var Comp: integer;
  630. begin
  631. Result:=Root;
  632. while (Result<>nil) do begin
  633. Comp:=OnCompareKeyWithData(Key,Result.Data);
  634. if Comp=0 then exit;
  635. if Comp<0 then begin
  636. Result:=Result.Left
  637. end else begin
  638. Result:=Result.Right
  639. end;
  640. end;
  641. end;
  642. function TAVLTree.FindLeftMostKey(Key: Pointer;
  643. OnCompareKeyWithData: TListSortCompare): TAVLTreeNode;
  644. begin
  645. Result:=FindLeftMostSameKey(FindKey(Key,OnCompareKeyWithData));
  646. end;
  647. function TAVLTree.FindRightMostKey(Key: Pointer;
  648. OnCompareKeyWithData: TListSortCompare): TAVLTreeNode;
  649. begin
  650. Result:=FindRightMostSameKey(FindKey(Key,OnCompareKeyWithData));
  651. end;
  652. function TAVLTree.FindLeftMostSameKey(ANode: TAVLTreeNode): TAVLTreeNode;
  653. var
  654. LeftNode: TAVLTreeNode;
  655. Data: Pointer;
  656. begin
  657. if ANode<>nil then begin
  658. Data:=ANode.Data;
  659. Result:=ANode;
  660. repeat
  661. LeftNode:=FindPrecessor(Result);
  662. if (LeftNode=nil) or (fOnCompare(Data,LeftNode.Data)<>0) then break;
  663. Result:=LeftNode;
  664. until false;
  665. end else begin
  666. Result:=nil;
  667. end;
  668. end;
  669. function TAVLTree.FindRightMostSameKey(ANode: TAVLTreeNode): TAVLTreeNode;
  670. var
  671. RightNode: TAVLTreeNode;
  672. Data: Pointer;
  673. begin
  674. if ANode<>nil then begin
  675. Data:=ANode.Data;
  676. Result:=ANode;
  677. repeat
  678. RightNode:=FindSuccessor(Result);
  679. if (RightNode=nil) or (fOnCompare(Data,RightNode.Data)<>0) then break;
  680. Result:=RightNode;
  681. until false;
  682. end else begin
  683. Result:=nil;
  684. end;
  685. end;
  686. function TAVLTree.FindNearest(Data: Pointer): TAVLTreeNode;
  687. var Comp: integer;
  688. begin
  689. Result:=Root;
  690. while (Result<>nil) do begin
  691. Comp:=fOnCompare(Data,Result.Data);
  692. if Comp=0 then exit;
  693. if Comp<0 then begin
  694. if Result.Left<>nil then
  695. Result:=Result.Left
  696. else
  697. exit;
  698. end else begin
  699. if Result.Right<>nil then
  700. Result:=Result.Right
  701. else
  702. exit;
  703. end;
  704. end;
  705. end;
  706. function TAVLTree.FindPointer(Data: Pointer): TAVLTreeNode;
  707. begin
  708. Result:=FindLeftMost(Data);
  709. while (Result<>nil) do begin
  710. if Result.Data=Data then break;
  711. Result:=FindSuccessor(Result);
  712. if fOnCompare(Data,Result.Data)<>0 then Result:=nil;
  713. end;
  714. end;
  715. function TAVLTree.FindLeftMost(Data: Pointer): TAVLTreeNode;
  716. var
  717. Left: TAVLTreeNode;
  718. begin
  719. Result:=Find(Data);
  720. while (Result<>nil) do begin
  721. Left:=FindPrecessor(Result);
  722. if (Left=nil) or (fOnCompare(Data,Left.Data)<>0) then break;
  723. Result:=Left;
  724. end;
  725. end;
  726. function TAVLTree.FindRightMost(Data: Pointer): TAVLTreeNode;
  727. var
  728. Right: TAVLTreeNode;
  729. begin
  730. Result:=Find(Data);
  731. while (Result<>nil) do begin
  732. Right:=FindSuccessor(Result);
  733. if (Right=nil) or (fOnCompare(Data,Right.Data)<>0) then break;
  734. Result:=Right;
  735. end;
  736. end;
  737. function TAVLTree.FindInsertPos(Data: Pointer): TAVLTreeNode;
  738. var Comp: integer;
  739. begin
  740. Result:=Root;
  741. while (Result<>nil) do begin
  742. Comp:=fOnCompare(Data,Result.Data);
  743. if Comp<0 then begin
  744. if Result.Left<>nil then
  745. Result:=Result.Left
  746. else
  747. exit;
  748. end else begin
  749. if Result.Right<>nil then
  750. Result:=Result.Right
  751. else
  752. exit;
  753. end;
  754. end;
  755. end;
  756. function TAVLTree.FindSuccessor(ANode: TAVLTreeNode): TAVLTreeNode;
  757. begin
  758. Result:=ANode.Right;
  759. if Result<>nil then begin
  760. while (Result.Left<>nil) do Result:=Result.Left;
  761. end else begin
  762. Result:=ANode;
  763. while (Result.Parent<>nil) and (Result.Parent.Right=Result) do
  764. Result:=Result.Parent;
  765. Result:=Result.Parent;
  766. end;
  767. end;
  768. function TAVLTree.FindPrecessor(ANode: TAVLTreeNode): TAVLTreeNode;
  769. begin
  770. Result:=ANode.Left;
  771. if Result<>nil then begin
  772. while (Result.Right<>nil) do Result:=Result.Right;
  773. end else begin
  774. Result:=ANode;
  775. while (Result.Parent<>nil) and (Result.Parent.Left=Result) do
  776. Result:=Result.Parent;
  777. Result:=Result.Parent;
  778. end;
  779. end;
  780. procedure TAVLTree.MoveDataLeftMost(var ANode: TAVLTreeNode);
  781. var LeftMost, PreNode: TAVLTreeNode;
  782. Data: Pointer;
  783. begin
  784. if ANode=nil then exit;
  785. LeftMost:=ANode;
  786. repeat
  787. PreNode:=FindPrecessor(LeftMost);
  788. if (PreNode=nil) or (FOnCompare(ANode,PreNode)<>0) then break;
  789. LeftMost:=PreNode;
  790. until false;
  791. if LeftMost=ANode then exit;
  792. Data:=LeftMost.Data;
  793. LeftMost.Data:=ANode.Data;
  794. ANode.Data:=Data;
  795. ANode:=LeftMost;
  796. end;
  797. procedure TAVLTree.MoveDataRightMost(var ANode: TAVLTreeNode);
  798. var RightMost, PostNode: TAVLTreeNode;
  799. Data: Pointer;
  800. begin
  801. if ANode=nil then exit;
  802. RightMost:=ANode;
  803. repeat
  804. PostNode:=FindSuccessor(RightMost);
  805. if (PostNode=nil) or (FOnCompare(ANode,PostNode)<>0) then break;
  806. RightMost:=PostNode;
  807. until false;
  808. if RightMost=ANode then exit;
  809. Data:=RightMost.Data;
  810. RightMost.Data:=ANode.Data;
  811. ANode.Data:=Data;
  812. ANode:=RightMost;
  813. end;
  814. function TAVLTree.ConsistencyCheck: integer;
  815. var RealCount: integer;
  816. function CheckNode(ANode: TAVLTreeNode): integer;
  817. var LeftDepth, RightDepth: integer;
  818. begin
  819. if ANode=nil then begin
  820. Result:=0;
  821. exit;
  822. end;
  823. inc(RealCount);
  824. // test left son
  825. if ANode.Left<>nil then begin
  826. if ANode.Left.Parent<>ANode then begin
  827. Result:=-2; exit;
  828. end;
  829. if fOnCompare(ANode.Left.Data,ANode.Data)>0 then begin
  830. //DebugLn('CCC-3 ',HexStr(PtrInt(ANode.Data),8),' ',HexStr(PtrInt(ANode.Left.Data),8));
  831. Result:=-3; exit;
  832. end;
  833. Result:=CheckNode(ANode.Left);
  834. if Result<>0 then exit;
  835. end;
  836. // test right son
  837. if ANode.Right<>nil then begin
  838. if ANode.Right.Parent<>ANode then begin
  839. Result:=-4; exit;
  840. end;
  841. if fOnCompare(ANode.Data,ANode.Right.Data)>0 then begin
  842. //DebugLn('CCC-5 ',HexStr(PtrInt(ANode.Data),8),' ',HexStr(PtrInt(ANode.Right.Data),8));
  843. Result:=-5; exit;
  844. end;
  845. Result:=CheckNode(ANode.Right);
  846. if Result<>0 then exit;
  847. end;
  848. // test balance
  849. if ANode.Left<>nil then
  850. LeftDepth:=ANode.Left.TreeDepth+1
  851. else
  852. LeftDepth:=0;
  853. if ANode.Right<>nil then
  854. RightDepth:=ANode.Right.TreeDepth+1
  855. else
  856. RightDepth:=0;
  857. if ANode.Balance<>(RightDepth-LeftDepth) then begin
  858. Result:=-6; exit;
  859. end;
  860. // ok
  861. Result:=0;
  862. end;
  863. // TAVLTree.ConsistencyCheck
  864. begin
  865. RealCount:=0;
  866. Result:=CheckNode(Root);
  867. if Result<>0 then exit;
  868. if FCount<>RealCount then begin
  869. Result:=-1;
  870. exit;
  871. end;
  872. end;
  873. procedure TAVLTree.FreeAndClear;
  874. procedure FreeNode(ANode: TAVLTreeNode);
  875. begin
  876. if ANode=nil then exit;
  877. FreeNode(ANode.Left);
  878. FreeNode(ANode.Right);
  879. if ANode.Data<>nil then TObject(ANode.Data).Free;
  880. ANode.Data:=nil;
  881. end;
  882. // TAVLTree.FreeAndClear
  883. begin
  884. // free all data
  885. FreeNode(Root);
  886. // free all nodes
  887. Clear;
  888. end;
  889. procedure TAVLTree.FreeAndDelete(ANode: TAVLTreeNode);
  890. var OldData: TObject;
  891. begin
  892. OldData:=TObject(ANode.Data);
  893. Delete(ANode);
  894. OldData.Free;
  895. end;
  896. procedure TAVLTree.WriteReportToStream(s: TStream; var StreamSize: int64);
  897. var h: string;
  898. procedure WriteStr(const Txt: string);
  899. begin
  900. if s<>nil then
  901. s.Write(Txt[1],length(Txt));
  902. inc(StreamSize,length(Txt));
  903. end;
  904. procedure WriteTreeNode(ANode: TAVLTreeNode; const Prefix: string);
  905. var b: string;
  906. begin
  907. if ANode=nil then exit;
  908. WriteTreeNode(ANode.Right,Prefix+' ');
  909. b:=Prefix+HexStr(PtrInt(ANode.Data),8)+' '
  910. +' Self='+HexStr(PtrInt(ANode),8)
  911. +' Parent='+HexStr(PtrInt(ANode.Parent),8)
  912. +' Balance='+IntToStr(ANode.Balance)
  913. +#13#10;
  914. WriteStr(b);
  915. WriteTreeNode(ANode.Left,Prefix+' ');
  916. end;
  917. // TAVLTree.WriteReportToStream
  918. begin
  919. h:='Consistency: '+IntToStr(ConsistencyCheck)+' ---------------------'+#13#10;
  920. WriteStr(h);
  921. WriteTreeNode(Root,' ');
  922. h:='-End-Of-AVL-Tree---------------------'+#13#10;
  923. WriteStr(h);
  924. end;
  925. function TAVLTree.ReportAsString: string;
  926. var ms: TMemoryStream;
  927. StreamSize: int64;
  928. begin
  929. Result:='';
  930. ms:=TMemoryStream.Create;
  931. try
  932. StreamSize:=0;
  933. WriteReportToStream(nil,StreamSize);
  934. ms.Size:=StreamSize;
  935. StreamSize:=0;
  936. WriteReportToStream(ms,StreamSize);
  937. StreamSize:=0;
  938. if StreamSize>0 then begin
  939. ms.Position:=0;
  940. SetLength(Result,StreamSize);
  941. ms.Read(Result[1],StreamSize);
  942. end;
  943. finally
  944. ms.Free;
  945. end;
  946. end;
  947. procedure TAVLTree.SetOnCompare(const AValue: TListSortCompare);
  948. var List: PPointer;
  949. ANode: TAVLTreeNode;
  950. i, OldCount: integer;
  951. begin
  952. if FOnCompare=AValue then exit;
  953. // sort the tree again
  954. if Count>0 then begin
  955. OldCount:=Count;
  956. GetMem(List,SizeOf(Pointer)*OldCount);
  957. try
  958. // save the data in a list
  959. ANode:=FindLowest;
  960. i:=0;
  961. while ANode<>nil do begin
  962. List[i]:=ANode.Data;
  963. inc(i);
  964. ANode:=FindSuccessor(ANode);
  965. end;
  966. // clear the tree
  967. Clear;
  968. // set the new compare function
  969. FOnCompare:=AValue;
  970. // re-add all nodes
  971. for i:=0 to OldCount-1 do
  972. Add(List[i]);
  973. finally
  974. FreeMem(List);
  975. end;
  976. end;
  977. end;
  978. { TAVLTreeNode }
  979. constructor TAVLTreeNode.Create;
  980. begin
  981. inherited Create;
  982. end;
  983. destructor TAVLTreeNode.Destroy;
  984. begin
  985. inherited Destroy;
  986. end;
  987. function TAVLTreeNode.TreeDepth: integer;
  988. // longest WAY down. e.g. only one node => 0 !
  989. var LeftDepth, RightDepth: integer;
  990. begin
  991. if Left<>nil then
  992. LeftDepth:=Left.TreeDepth+1
  993. else
  994. LeftDepth:=0;
  995. if Right<>nil then
  996. RightDepth:=Right.TreeDepth+1
  997. else
  998. RightDepth:=0;
  999. if LeftDepth>RightDepth then
  1000. Result:=LeftDepth
  1001. else
  1002. Result:=RightDepth;
  1003. end;
  1004. procedure TAVLTreeNode.Clear;
  1005. begin
  1006. Parent:=nil;
  1007. Left:=nil;
  1008. Right:=nil;
  1009. Balance:=0;
  1010. Data:=nil;
  1011. end;
  1012. { TAVLTreeNodeMemManager }
  1013. constructor TAVLTreeNodeMemManager.Create;
  1014. begin
  1015. inherited Create;
  1016. FFirstFree:=nil;
  1017. FFreeCount:=0;
  1018. FCount:=0;
  1019. FMinFree:=100;
  1020. FMaxFreeRatio:=8; // 1:1
  1021. end;
  1022. destructor TAVLTreeNodeMemManager.Destroy;
  1023. begin
  1024. Clear;
  1025. inherited Destroy;
  1026. end;
  1027. procedure TAVLTreeNodeMemManager.DisposeNode(ANode: TAVLTreeNode);
  1028. begin
  1029. if ANode=nil then exit;
  1030. if (FFreeCount<FMinFree) or (FFreeCount<((FCount shr 3)*FMaxFreeRatio)) then
  1031. begin
  1032. // add ANode to Free list
  1033. ANode.Clear;
  1034. ANode.Right:=FFirstFree;
  1035. FFirstFree:=ANode;
  1036. inc(FFreeCount);
  1037. if (FFreeCount>(((8+FMaxFreeRatio)*FCount) shr 3)) then begin
  1038. DisposeFirstFreeNode;
  1039. DisposeFirstFreeNode;
  1040. end;
  1041. end else begin
  1042. // free list full -> free the ANode
  1043. ANode.Free;
  1044. end;
  1045. dec(FCount);
  1046. end;
  1047. function TAVLTreeNodeMemManager.NewNode: TAVLTreeNode;
  1048. begin
  1049. if FFirstFree<>nil then begin
  1050. // take from free list
  1051. Result:=FFirstFree;
  1052. FFirstFree:=FFirstFree.Right;
  1053. Result.Right:=nil;
  1054. end else begin
  1055. // free list empty -> create new node
  1056. Result:=TAVLTreeNode.Create;
  1057. end;
  1058. inc(FCount);
  1059. end;
  1060. procedure TAVLTreeNodeMemManager.Clear;
  1061. var ANode: TAVLTreeNode;
  1062. begin
  1063. while FFirstFree<>nil do begin
  1064. ANode:=FFirstFree;
  1065. FFirstFree:=FFirstFree.Right;
  1066. ANode.Right:=nil;
  1067. ANode.Free;
  1068. end;
  1069. FFreeCount:=0;
  1070. end;
  1071. procedure TAVLTreeNodeMemManager.SetMaxFreeRatio(NewValue: integer);
  1072. begin
  1073. if NewValue<0 then NewValue:=0;
  1074. if NewValue=FMaxFreeRatio then exit;
  1075. FMaxFreeRatio:=NewValue;
  1076. end;
  1077. procedure TAVLTreeNodeMemManager.SetMinFree(NewValue: integer);
  1078. begin
  1079. if NewValue<0 then NewValue:=0;
  1080. if NewValue=FMinFree then exit;
  1081. FMinFree:=NewValue;
  1082. end;
  1083. procedure TAVLTreeNodeMemManager.DisposeFirstFreeNode;
  1084. var OldNode: TAVLTreeNode;
  1085. begin
  1086. if FFirstFree=nil then exit;
  1087. OldNode:=FFirstFree;
  1088. FFirstFree:=FFirstFree.Right;
  1089. dec(FFreeCount);
  1090. OldNode.Right:=nil;
  1091. OldNode.Free;
  1092. end;
  1093. initialization
  1094. NodeMemManager:=TAVLTreeNodeMemManager.Create;
  1095. finalization
  1096. NodeMemManager.Free;
  1097. NodeMemManager:=nil;
  1098. end.