Stage.RedBlackTree.pas 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781
  1. //
  2. // The graphics engine GXScene https://github.com/glscene
  3. //
  4. unit Stage.RedBlackTree;
  5. (*
  6. USAGE
  7. The TRedBlackTree generic class behaves somewhat like a TList:
  8. it stores _Value_ by _Key_
  9. and uses the same comparison function as TList.Sort (TListSortCompare).
  10. Functions Clear, Add, Delete, First and Last are equivalent,
  11. except that First and Last return a _Key_ so they
  12. can be used for comparisons in loops.
  13. All _Key_ occur only once in the tree if DuplicateKeys is False:
  14. when the same value is added twice, the second one is not stored.
  15. When DuplicateKeys is enabled the second comparison function is used
  16. for sort _Value_ and it duplicates not allowed.
  17. To be able to manage the tree, the Create constructor has an argument
  18. specifying the comparison function that should be used.
  19. The function Find can be used to find a _Value_ that was put in the tree,
  20. it searches for the given _Key_ using the comparison function given
  21. at time of object creation.
  22. The functions NextKey and PrevKey can be used to "walk" through the tree:
  23. given a _Key_, NextKey replace it with the smallest key that
  24. is larger than _Key_, PrevKey returns the largest key that is
  25. smaller than _Key_. For Last and First key result not returned.
  26. *)
  27. interface
  28. {$I Stage.Defines.inc}
  29. uses
  30. System.Classes;
  31. type
  32. TRBColor = (clRed, clBlack);
  33. {$IFDEF GENERIC_PREFIX}
  34. generic
  35. {$ENDIF}
  36. GRedBlackTree<TKey, TValue> = class
  37. public
  38. type
  39. TKeyCompareFunc = function(const Item1, Item2: TKey): Integer;
  40. TValueCompareFunc = function(const Item1, Item2: TValue): Boolean;
  41. TForEachProc = procedure(AKey: TKey; AValue: TValue; out AContinue: Boolean);
  42. TRBNode = class Key: TKey;
  43. Left, Right, Parent, Twin: TRBNode;
  44. Color:
  45. TRBColor;
  46. Value:
  47. TValue;
  48. end;
  49. var
  50. FRoot: TRBNode;
  51. FLeftmost: TRBNode;
  52. FRightmost: TRBNode;
  53. FLastFound: TRBNode;
  54. FLastNode: TRBNode;
  55. FCount: Integer;
  56. FKeyCompareFunc: TKeyCompareFunc;
  57. FDuplicateKeys: Boolean;
  58. FValueCompareFunc: TValueCompareFunc;
  59. FOnChange: TNotifyEvent;
  60. function FindNode(const Key: TKey): TRBNode;
  61. procedure RotateLeft(var x: TRBNode);
  62. procedure RotateRight(var x: TRBNode);
  63. function Minimum(var x: TRBNode): TRBNode;
  64. function Maximum(var x: TRBNode): TRBNode;
  65. function GetFirst: TKey;
  66. function GetLast: TKey;
  67. procedure SetDuplicateKeys(Value: Boolean);
  68. class procedure FastErase(x: TRBNode);
  69. public
  70. constructor Create(KeyCompare: TKeyCompareFunc;
  71. ValueCompare: TValueCompareFunc);
  72. destructor Destroy; override;
  73. procedure Clear;
  74. // Find value by key.
  75. function Find(const Key: TKey; out Value: TValue): Boolean;
  76. function NextKey(var Key: TKey; out Value: TValue): Boolean;
  77. function PrevKey(var Key: TKey; out Value: TValue): Boolean;
  78. function NextDublicate(out Value: TValue): Boolean;
  79. procedure Add(const Key: TKey; const Value: TValue);
  80. procedure Delete(const Key: TKey);
  81. procedure ForEach(AProc: TForEachProc);
  82. property Count: Integer read FCount;
  83. property First: TKey read GetFirst;
  84. property Last: TKey read GetLast;
  85. property DuplicateKeys: Boolean read FDuplicateKeys
  86. write SetDuplicateKeys;
  87. property OnChange: TNotifyEvent read FOnChange
  88. write FOnChange;
  89. end;
  90. function CompareInteger(const Item1, Item2: Integer): Integer;
  91. implementation // -------------------------------------------------------------
  92. function CompareInteger(const Item1, Item2: Integer): Integer;
  93. begin
  94. if Item1 < Item2 then
  95. begin
  96. Result := -1;
  97. end
  98. else if (Item1 = Item2) then
  99. begin
  100. Result := 0;
  101. end
  102. else
  103. begin
  104. Result := 1;
  105. end
  106. end;
  107. constructor GRedBlackTree<TKey, TValue>.Create(KeyCompare: TKeyCompareFunc;
  108. ValueCompare: TValueCompareFunc);
  109. begin
  110. inherited Create;
  111. Assert(Assigned(KeyCompare));
  112. FKeyCompareFunc := KeyCompare;
  113. FValueCompareFunc := ValueCompare;
  114. FRoot := nil;
  115. FLeftmost := nil;
  116. FRightmost := nil;
  117. FDuplicateKeys := Assigned(ValueCompare);
  118. end;
  119. destructor GRedBlackTree<TKey, TValue>.Destroy;
  120. begin
  121. Clear;
  122. inherited Destroy;
  123. end;
  124. class procedure GRedBlackTree<TKey, TValue>.FastErase(x: TRBNode);
  125. var
  126. y: TRBNode;
  127. begin
  128. if (x.Left <> nil) then
  129. FastErase(x.Left);
  130. if (x.Right <> nil) then
  131. FastErase(x.Right);
  132. repeat
  133. y := x;
  134. x := x.Twin;
  135. y.Destroy;
  136. until x = nil;
  137. end;
  138. procedure GRedBlackTree<TKey, TValue>.Clear;
  139. begin
  140. if (FRoot <> nil) then
  141. FastErase(FRoot);
  142. FRoot := nil;
  143. FLeftmost := nil;
  144. FRightmost := nil;
  145. FCount := 0;
  146. if Assigned(FOnChange) then
  147. FOnChange(Self);
  148. end;
  149. function GRedBlackTree<TKey, TValue>.Find(const Key: TKey;
  150. out Value: TValue): Boolean;
  151. begin
  152. FLastFound := FindNode(Key);
  153. Result := Assigned(FLastFound);
  154. if Result then
  155. Value := FLastFound.Value;
  156. end;
  157. function GRedBlackTree<TKey, TValue>.FindNode(const Key: TKey): TRBNode;
  158. var
  159. cmp: Integer;
  160. begin
  161. Result := FRoot;
  162. while (Result <> nil) do
  163. begin
  164. cmp := FKeyCompareFunc(Result.Key, Key);
  165. if cmp < 0 then
  166. begin
  167. Result := Result.Right;
  168. end
  169. else if cmp > 0 then
  170. begin
  171. Result := Result.Left;
  172. end
  173. else
  174. begin
  175. break;
  176. end;
  177. end;
  178. end;
  179. function GRedBlackTree<TKey, TValue>.NextDublicate(out Value: TValue): Boolean;
  180. begin
  181. if Assigned(FLastFound) then
  182. begin
  183. if Assigned(FLastFound.Twin) then
  184. begin
  185. FLastFound := FLastFound.Twin;
  186. Value := FLastFound.Value;
  187. exit(True);
  188. end;
  189. end;
  190. Result := False;
  191. end;
  192. procedure GRedBlackTree<TKey, TValue>.RotateLeft(var x: TRBNode);
  193. var
  194. y: TRBNode;
  195. begin
  196. y := x.Right;
  197. x.Right := y.Left;
  198. if (y.Left <> nil) then
  199. begin
  200. y.Left.Parent := x;
  201. end;
  202. y.Parent := x.Parent;
  203. if (x = FRoot) then
  204. begin
  205. FRoot := y;
  206. end
  207. else if (x = x.Parent.Left) then
  208. begin
  209. x.Parent.Left := y;
  210. end
  211. else
  212. begin
  213. x.Parent.Right := y;
  214. end;
  215. y.Left := x;
  216. x.Parent := y;
  217. end;
  218. procedure GRedBlackTree<TKey, TValue>.RotateRight(var x: TRBNode);
  219. var
  220. y: TRBNode;
  221. begin
  222. y := x.Left;
  223. x.Left := y.Right;
  224. if (y.Right <> nil) then
  225. begin
  226. y.Right.Parent := x;
  227. end;
  228. y.Parent := x.Parent;
  229. if (x = FRoot) then
  230. begin
  231. FRoot := y;
  232. end
  233. else if (x = x.Parent.Right) then
  234. begin
  235. x.Parent.Right := y;
  236. end
  237. else
  238. begin
  239. x.Parent.Left := y;
  240. end;
  241. y.Right := x;
  242. x.Parent := y;
  243. end;
  244. function GRedBlackTree<TKey, TValue>.Minimum(var x: TRBNode): TRBNode;
  245. begin
  246. Result := x;
  247. while (Result.Left <> nil) do
  248. Result := Result.Left;
  249. end;
  250. function GRedBlackTree<TKey, TValue>.Maximum(var x: TRBNode): TRBNode;
  251. begin
  252. Result := x;
  253. while (Result.Right <> nil) do
  254. Result := Result.Right;
  255. end;
  256. procedure GRedBlackTree<TKey, TValue>.Add(const Key: TKey; const Value: TValue);
  257. var
  258. x, y, z, zpp: TRBNode;
  259. cmp: Integer;
  260. begin
  261. z := TRBNode.Create;
  262. { Initialize fields in new node z }
  263. z.Key := Key;
  264. z.Left := nil;
  265. z.Right := nil;
  266. z.Color := clRed;
  267. z.Value := Value;
  268. z.Twin := nil;
  269. { Maintain FLeftmost and FRightmost nodes }
  270. if ((FLeftmost = nil) or (FKeyCompareFunc(Key, FLeftmost.Key) < 0)) then
  271. begin
  272. FLeftmost := z;
  273. end;
  274. if ((FRightmost = nil) or (FKeyCompareFunc(FRightmost.Key, Key) < 0)) then
  275. begin
  276. FRightmost := z;
  277. end;
  278. { Insert node z }
  279. y := nil;
  280. x := FRoot;
  281. while (x <> nil) do
  282. begin
  283. y := x;
  284. cmp := FKeyCompareFunc(Key, x.Key);
  285. if cmp < 0 then
  286. x := x.Left
  287. else if cmp > 0 then
  288. x := x.Right
  289. else
  290. begin
  291. { Key already exists in tree. }
  292. if FDuplicateKeys then
  293. begin
  294. { Check twins chain for value dublicate. }
  295. repeat
  296. if FValueCompareFunc(Value, x.Value) then
  297. begin
  298. y := nil;
  299. break;
  300. end;
  301. y := x;
  302. x := x.Twin;
  303. until x = nil;
  304. if Assigned(y) then
  305. begin
  306. { Add dublicate key to end of twins chain. }
  307. y.Twin := z;
  308. Inc(FCount);
  309. if Assigned(FOnChange) then
  310. FOnChange(Self);
  311. exit;
  312. end;
  313. // Value already exists in tree.
  314. end;
  315. z.Destroy;
  316. // a jzombi: memory leak: if we don't put it in the tree, we shouldn't hold it in the memory
  317. exit;
  318. end;
  319. end;
  320. z.Parent := y;
  321. if (y = nil) then
  322. begin
  323. FRoot := z;
  324. end
  325. else if (FKeyCompareFunc(Key, y.Key) < 0) then
  326. begin
  327. y.Left := z;
  328. end
  329. else
  330. begin
  331. y.Right := z;
  332. end;
  333. { Rebalance tree }
  334. while ((z <> FRoot) and (z.Parent.Color = clRed)) do
  335. begin
  336. zpp := z.Parent.Parent;
  337. if (z.Parent = zpp.Left) then
  338. begin
  339. y := zpp.Right;
  340. if ((y <> nil) and (y.Color = clRed)) then
  341. begin
  342. z.Parent.Color := clBlack;
  343. y.Color := clBlack;
  344. zpp.Color := clRed;
  345. z := zpp;
  346. end
  347. else
  348. begin
  349. if (z = z.Parent.Right) then
  350. begin
  351. z := z.Parent;
  352. RotateLeft(z);
  353. end;
  354. z.Parent.Color := clBlack;
  355. zpp.Color := clRed;
  356. RotateRight(zpp);
  357. end;
  358. end
  359. else
  360. begin
  361. y := zpp.Left;
  362. if ((y <> nil) and (y.Color = clRed)) then
  363. begin
  364. z.Parent.Color := clBlack;
  365. y.Color := clBlack;
  366. zpp.Color := clRed; // c jzombi: zpp.color := clRed;
  367. z := zpp;
  368. end
  369. else
  370. begin
  371. if (z = z.Parent.Left) then
  372. begin
  373. z := z.Parent;
  374. RotateRight(z);
  375. end;
  376. z.Parent.Color := clBlack;
  377. zpp.Color := clRed; // c jzombi: zpp.color := clRed;
  378. RotateLeft(zpp);
  379. end;
  380. end;
  381. end;
  382. FRoot.Color := clBlack;
  383. Inc(FCount);
  384. if Assigned(FOnChange) then
  385. FOnChange(Self);
  386. end;
  387. procedure GRedBlackTree<TKey, TValue>.Delete(const Key: TKey);
  388. var
  389. w, x, y, z, x_parent: TRBNode;
  390. tmpcol: TRBColor;
  391. begin
  392. z := FindNode(Key);
  393. if z = nil then
  394. exit;
  395. y := z;
  396. x := nil;
  397. x_parent := nil;
  398. if (y.Left = nil) then
  399. begin // z has at most one non-null child. y = z.
  400. x := y.Right; // x might be null.
  401. end
  402. else
  403. begin
  404. if (y.Right = nil) then
  405. begin // z has exactly one non-null child. y = z.
  406. x := y.Left; // x is not null.
  407. end
  408. else
  409. begin
  410. // z has two non-null children. Set y to
  411. y := y.Right; // z's successor. x might be null.
  412. while (y.Left <> nil) do
  413. begin
  414. y := y.Left;
  415. end;
  416. x := y.Right;
  417. end;
  418. end;
  419. if (y <> z) then
  420. begin
  421. (* "copy y's sattelite data into z"
  422. relink y in place of z. y is z's successor *)
  423. z.Left.Parent := y;
  424. y.Left := z.Left;
  425. if (y <> z.Right) then
  426. begin
  427. x_parent := y.Parent;
  428. if (x <> nil) then
  429. begin
  430. x.Parent := y.Parent;
  431. end;
  432. y.Parent.Left := x; // y must be a child of left
  433. y.Right := z.Right;
  434. z.Right.Parent := y;
  435. end
  436. else
  437. begin
  438. x_parent := y;
  439. end;
  440. if (FRoot = z) then
  441. begin
  442. FRoot := y;
  443. end
  444. else if (z.Parent.Left = z) then
  445. begin
  446. z.Parent.Left := y;
  447. end
  448. else
  449. begin
  450. z.Parent.Right := y;
  451. end;
  452. y.Parent := z.Parent;
  453. tmpcol := y.Color;
  454. y.Color := z.Color;
  455. z.Color := tmpcol;
  456. y := z;
  457. // y now points to node to be actually deleted
  458. end
  459. else
  460. begin // y = z
  461. x_parent := y.Parent;
  462. if (x <> nil) then
  463. begin
  464. x.Parent := y.Parent;
  465. end;
  466. if (FRoot = z) then
  467. begin
  468. FRoot := x;
  469. end
  470. else
  471. begin
  472. if (z.Parent.Left = z) then
  473. begin
  474. z.Parent.Left := x;
  475. end
  476. else
  477. begin
  478. z.Parent.Right := x;
  479. end;
  480. end;
  481. if (FLeftmost = z) then
  482. begin
  483. if (z.Right = nil) then
  484. begin // z.left must be null also
  485. FLeftmost := z.Parent;
  486. end
  487. else
  488. begin
  489. FLeftmost := Minimum(x);
  490. end;
  491. end;
  492. if (FRightmost = z) then
  493. begin
  494. if (z.Left = nil) then
  495. begin // z.right must be null also
  496. FRightmost := z.Parent;
  497. end
  498. else
  499. begin // x == z.left
  500. FRightmost := Maximum(x);
  501. end;
  502. end;
  503. end;
  504. // Rebalance tree
  505. if (y.Color = clBlack) then
  506. begin
  507. while ((x <> FRoot) and ((x = nil) or (x.Color = clBlack))) do
  508. begin
  509. if (x = x_parent.Left) then
  510. begin
  511. w := x_parent.Right;
  512. if (w.Color = clRed) then
  513. begin
  514. w.Color := clBlack;
  515. x_parent.Color := clRed;
  516. RotateLeft(x_parent);
  517. w := x_parent.Right;
  518. end;
  519. if (((w.Left = nil) or (w.Left.Color = clBlack)) and
  520. ((w.Right = nil) or (w.Right.Color = clBlack))) then
  521. begin
  522. w.Color := clRed;
  523. x := x_parent;
  524. x_parent := x_parent.Parent;
  525. end
  526. else
  527. begin
  528. if ((w.Right = nil) or (w.Right.Color = clBlack)) then
  529. begin
  530. w.Left.Color := clBlack;
  531. w.Color := clRed;
  532. RotateRight(w);
  533. w := x_parent.Right;
  534. end;
  535. w.Color := x_parent.Color;
  536. x_parent.Color := clBlack;
  537. if (w.Right <> nil) then
  538. begin
  539. w.Right.Color := clBlack;
  540. end;
  541. RotateLeft(x_parent);
  542. x := FRoot; { break; }
  543. end
  544. end
  545. else
  546. begin
  547. { same as above, with right <. left. }
  548. w := x_parent.Left;
  549. if (w.Color = clRed) then
  550. begin
  551. w.Color := clBlack;
  552. x_parent.Color := clRed;
  553. RotateRight(x_parent);
  554. w := x_parent.Left;
  555. end;
  556. if (((w.Right = nil) or (w.Right.Color = clBlack)) and
  557. ((w.Left = nil) or (w.Left.Color = clBlack))) then
  558. begin
  559. w.Color := clRed;
  560. x := x_parent;
  561. x_parent := x_parent.Parent;
  562. end
  563. else
  564. begin
  565. if ((w.Left = nil) or (w.Left.Color = clBlack)) then
  566. begin
  567. w.Right.Color := clBlack;
  568. w.Color := clRed;
  569. RotateLeft(w);
  570. w := x_parent.Left;
  571. end;
  572. w.Color := x_parent.Color;
  573. x_parent.Color := clBlack;
  574. if (w.Left <> nil) then
  575. begin
  576. w.Left.Color := clBlack;
  577. end;
  578. RotateRight(x_parent);
  579. x := FRoot; // break;
  580. end;
  581. end;
  582. end;
  583. if (x <> nil) then
  584. begin
  585. x.Color := clBlack;
  586. end;
  587. end;
  588. while Assigned(y.Twin) do
  589. begin
  590. z := y;
  591. y := y.Twin;
  592. z.Destroy;
  593. end;
  594. y.Destroy;
  595. Dec(FCount);
  596. if Assigned(FOnChange) then
  597. FOnChange(Self);
  598. end;
  599. function GRedBlackTree<TKey, TValue>.NextKey(var Key: TKey;
  600. out Value: TValue): Boolean;
  601. var
  602. x, y: TRBNode;
  603. begin
  604. if Assigned(FLastNode) and (FKeyCompareFunc(FLastNode.Key, Key) = 0) then
  605. x := FLastNode
  606. else
  607. x := FindNode(Key);
  608. if x = nil then
  609. exit;
  610. if (x.Right <> nil) then
  611. begin
  612. x := x.Right;
  613. while (x.Left <> nil) do
  614. begin
  615. x := x.Left;
  616. end;
  617. end
  618. else if (x.Parent <> nil) then
  619. begin
  620. y := x.Parent;
  621. while Assigned(y) and (x = y.Right) do
  622. begin
  623. x := y;
  624. y := y.Parent;
  625. end;
  626. if (x.Right <> y) then
  627. x := y;
  628. end
  629. else
  630. x := FRoot;
  631. if x = nil then
  632. exit(False);
  633. Key := x.Key;
  634. FLastNode := x;
  635. Value := x.Value;
  636. Result := True;
  637. end;
  638. function GRedBlackTree<TKey, TValue>.PrevKey(var Key: TKey;
  639. out Value: TValue): Boolean;
  640. var
  641. x, y: TRBNode;
  642. begin
  643. if Assigned(FLastNode) and (FKeyCompareFunc(FLastNode.Key, Key) = 0) then
  644. x := FLastNode
  645. else
  646. x := FindNode(Key);
  647. if x = nil then
  648. exit(False);
  649. if (x.Left <> nil) then
  650. begin
  651. y := x.Left;
  652. while (y.Right <> nil) do
  653. begin
  654. y := y.Right;
  655. end;
  656. x := y;
  657. end
  658. else if (x.Parent <> nil) then
  659. begin
  660. y := x.Parent;
  661. while (x = y.Left) do
  662. begin
  663. x := y;
  664. y := y.Parent;
  665. end;
  666. x := y;
  667. end
  668. else
  669. x := FRoot;
  670. if x = nil then
  671. exit(False);
  672. Key := x.Key;
  673. FLastNode := x;
  674. Value := x.Value;
  675. Result := True;
  676. end;
  677. function GRedBlackTree<TKey, TValue>.GetFirst: TKey;
  678. begin
  679. Result := FLeftmost.Key;
  680. end;
  681. function GRedBlackTree<TKey, TValue>.GetLast: TKey;
  682. begin
  683. Result := FRightmost.Key;
  684. end;
  685. procedure GRedBlackTree<TKey, TValue>.ForEach(AProc: TForEachProc);
  686. var
  687. x, y, z: TRBNode;
  688. cont: Boolean;
  689. begin
  690. if Assigned(FLeftmost) then
  691. begin
  692. x := FLeftmost;
  693. repeat
  694. z := x;
  695. repeat
  696. AProc(z.Key, z.Value, cont);
  697. if not cont then
  698. exit;
  699. z := z.Twin;
  700. until z = nil;
  701. // Next node
  702. if (x.Right <> nil) then
  703. begin
  704. x := x.Right;
  705. while (x.Left <> nil) do
  706. begin
  707. x := x.Left;
  708. end;
  709. end
  710. else if (x.Parent <> nil) then
  711. begin
  712. y := x.Parent;
  713. while (x = y.Right) do
  714. begin
  715. x := y;
  716. y := y.Parent;
  717. end;
  718. if (x.Right <> y) then
  719. x := y;
  720. end
  721. else
  722. x := FRoot;
  723. until x = FRightmost;
  724. if cont and (FLeftmost <> FRightmost) then
  725. AProc(FRightmost.Key, FRightmost.Value, cont);
  726. end;
  727. end;
  728. procedure GRedBlackTree<TKey, TValue>.SetDuplicateKeys(Value: Boolean);
  729. begin
  730. if Value and Assigned(FValueCompareFunc) then
  731. FDuplicateKeys := True
  732. else
  733. FDuplicateKeys := False;
  734. end;
  735. end.