avl_tree.pp 30 KB

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