1
unit LUX.Data.Tree.core;
10
TNodeProc<_TNode_: class> = reference to procedure(const Node_: _TNode_);
15
function Get_Parent: TTreeItem; virtual;
16
procedure Set_Parent(const Parent_: TTreeItem); virtual;
17
function Get_Order: Integer; virtual;
18
procedure Set_Order(const Order_: Integer); virtual;
19
function Get_Prev: TTreeItem; virtual;
20
procedure Set_Prev(const Prev_: TTreeItem); virtual;
21
function Get_Next: TTreeItem; virtual;
22
procedure Set_Next(const Next_: TTreeItem); virtual;
23
function Get_Links(const I_: Integer): TTreeItem; virtual;
24
procedure Set_Links(const I_: Integer; const Link_: TTreeItem); virtual;
25
function Get_LinksN: Integer; virtual;
26
procedure Set_LinksN(const LinksN_: Integer); virtual;
27
function Get_ChildsN: Integer; virtual;
28
procedure Set_ChildsN(const ChildsN_: Integer); virtual;
29
function Get_MaxOrder: Integer; virtual;
30
procedure Set_MaxOrder(const MaxOrder_: Integer); virtual;
31
property _Parent: TTreeItem read Get_Parent write Set_Parent;
32
property _Order: Integer read Get_Order write Set_Order;
33
property _Prev: TTreeItem read Get_Prev write Set_Prev;
34
property _Next: TTreeItem read Get_Next write Set_Next;
35
property _Links[const I_: Integer]: TTreeItem read Get_Links
37
property _LinksN: Integer read Get_LinksN write Set_LinksN;
38
property _ChildsN: Integer read Get_ChildsN write Set_ChildsN;
39
property _MaxOrder: Integer read Get_MaxOrder write Set_MaxOrder;
43
TTreeItem = class(TTreeAtom)
45
function Get_Zero: TTreeItem;
46
procedure Set_Zero(const Zero_: TTreeItem);
47
function GetIsOrdered: Boolean;
48
class procedure Bind(const C0_, C1_: TTreeItem); overload; inline;
49
class procedure Bind(const C0_, C1_, C2_: TTreeItem); overload; inline;
50
class procedure Bind(const C0_, C1_, C2_, C3_: TTreeItem); overload; inline;
52
function GetParent: TTreeItem;
53
procedure SetParent(const Parent_: TTreeItem);
54
function GetOrder: Integer;
55
procedure SetOrder(const Order_: Integer);
56
function GetHead: TTreeItem;
57
function GetTail: TTreeItem;
58
function GetChilds(const I_: Integer): TTreeItem;
59
procedure SetChilds(const I_: Integer; const Child_: TTreeItem);
60
function GetChildsN: Integer;
61
function GetRootNode: TTreeItem;
62
property _Zero: TTreeItem read Get_Zero write Set_Zero;
63
property IsOrdered: Boolean read GetIsOrdered;
64
procedure FindTo(const Child_: TTreeItem); overload;
65
procedure FindTo(const Order_: Integer); overload;
66
procedure _Insert(const C0_, C1_, C2_: TTreeItem);
68
procedure OnInsertChild(const Child_: TTreeItem); virtual;
69
procedure OnRemoveChild(const Child_: TTreeItem); virtual;
71
property Parent: TTreeItem read GetParent write SetParent;
72
property Order: Integer read GetOrder write SetOrder;
73
property Head: TTreeItem read GetHead;
74
property Tail: TTreeItem read GetTail;
75
property Childs[const I_: Integer]: TTreeItem read GetChilds
76
write SetChilds; default;
77
property ChildsN: Integer read GetChildsN;
78
property RootNode: TTreeItem read GetRootNode;
80
procedure RemoveChild(const Child_: TTreeItem);
81
procedure DeleteChilds; virtual;
82
procedure _InsertHead(const Child_: TTreeItem);
83
procedure _InsertTail(const Child_: TTreeItem);
84
procedure _InsertPrev(const Sibli_: TTreeItem);
85
procedure _InsertNext(const Sibli_: TTreeItem);
86
procedure InsertHead(const Child_: TTreeItem);
87
procedure InsertTail(const Child_: TTreeItem);
88
procedure InsertPrev(const Sibli_: TTreeItem);
89
procedure InsertNext(const Sibli_: TTreeItem);
90
class procedure Swap(const C1_, C2_: TTreeItem); overload;
91
procedure Swap(const I1_, I2_: Integer); overload;
92
procedure RunFamily(const Proc_: TNodeProc<TTreeItem>);
95
//=====================================================================
98
function TTreeAtom.Get_Parent: TTreeItem;
103
procedure TTreeAtom.Set_Parent(const Parent_: TTreeItem);
108
function TTreeAtom.Get_Order: Integer;
113
procedure TTreeAtom.Set_Order(const Order_: Integer);
118
function TTreeAtom.Get_Prev: TTreeItem;
123
procedure TTreeAtom.Set_Prev(const Prev_: TTreeItem);
128
function TTreeAtom.Get_Next: TTreeItem;
133
procedure TTreeAtom.Set_Next(const Next_: TTreeItem);
138
function TTreeAtom.Get_Links(const I_: Integer): TTreeItem;
143
procedure TTreeAtom.Set_Links(const I_: Integer; const Link_: TTreeItem);
148
function TTreeAtom.Get_LinksN: Integer;
153
procedure TTreeAtom.Set_LinksN(const LinksN_: Integer);
158
function TTreeAtom.Get_ChildsN: Integer;
163
procedure TTreeAtom.Set_ChildsN(const ChildsN_: Integer);
168
function TTreeAtom.Get_MaxOrder: Integer;
173
procedure TTreeAtom.Set_MaxOrder(const MaxOrder_: Integer);
178
function TTreeItem.Get_Zero: TTreeItem;
180
Result := _Links[-1];
183
procedure TTreeItem.Set_Zero(const Zero_: TTreeItem);
188
// ------------------------------------------------------------------------------
190
function TTreeItem.GetIsOrdered: Boolean;
192
Result := (_Order <= _Parent._MaxOrder) and (_Parent._Links[_Order] = Self);
195
class procedure TTreeItem.Bind(const C0_, C1_: TTreeItem);
201
class procedure TTreeItem.Bind(const C0_, C1_, C2_: TTreeItem);
207
class procedure TTreeItem.Bind(const C0_, C1_, C2_, C3_: TTreeItem);
214
function TTreeItem.GetParent: TTreeItem;
219
procedure TTreeItem.SetParent(const Parent_: TTreeItem);
223
if Assigned(Parent_) then
224
Parent_._InsertTail(Self);
227
// ------------------------------------------------------------------------------
229
function TTreeItem.GetOrder: Integer;
231
if not IsOrdered then
232
_Parent.FindTo(Self);
237
procedure TTreeItem.SetOrder(const Order_: Integer);
239
Swap(Self, _Parent.Childs[Order_]);
242
// ------------------------------------------------------------------------------
244
function TTreeItem.GetHead: TTreeItem;
246
Result := _Zero._Next;
249
function TTreeItem.GetTail: TTreeItem;
251
Result := _Zero._Prev;
254
// ------------------------------------------------------------------------------
256
function TTreeItem.GetChilds(const I_: Integer): TTreeItem;
258
if I_ > _MaxOrder then
261
Result := _Links[I_];
264
procedure TTreeItem.SetChilds(const I_: Integer; const Child_: TTreeItem);
270
S := Childs[I_]._Prev;
275
S.InsertNext(Child_);
278
function TTreeItem.GetChildsN: Integer;
283
function TTreeItem.GetRootNode: TTreeItem;
287
while Assigned(Result.Parent) do
288
Result := Result.Parent;
291
procedure TTreeItem.FindTo(const Child_: TTreeItem);
295
if _ChildsN > _LinksN then
298
P := _Links[_MaxOrder];
303
_MaxOrder := _MaxOrder + 1;
305
_Links[_MaxOrder] := P;
306
P._Order := _MaxOrder;
311
procedure TTreeItem.FindTo(const Order_: Integer);
316
if _ChildsN > _LinksN then
319
P := _Links[_MaxOrder];
321
for I := _MaxOrder + 1 to Order_ do
332
// ------------------------------------------------------------------------------
334
procedure TTreeItem._Insert(const C0_, C1_, C2_: TTreeItem);
340
_ChildsN := _ChildsN + 1;
345
procedure TTreeItem._Remove;
350
_Parent._MaxOrder := _Order - 1;
354
_ChildsN := _ChildsN - 1;
356
if _ChildsN * 2 < _LinksN then
366
// ------------------------------------------------------------------------------
368
procedure TTreeItem.OnInsertChild(const Child_: TTreeItem);
370
if Assigned(_Parent) then
371
_Parent.OnInsertChild(Child_);
374
procedure TTreeItem.OnRemoveChild(const Child_: TTreeItem);
376
if Assigned(_Parent) then
377
_Parent.OnRemoveChild(Child_);
380
procedure TTreeItem.Remove;
382
if Assigned(_Parent) then
386
procedure TTreeItem.RemoveChild(const Child_: TTreeItem);
388
if Self = Child_.Parent then
392
// ------------------------------------------------------------------------------
394
procedure TTreeItem.DeleteChilds;
398
for N := 1 to _ChildsN do
402
// ------------------------------------------------------------------------------
404
procedure TTreeItem._InsertHead(const Child_: TTreeItem);
406
_Insert(_Zero, Child_, Head);
408
_MaxOrder := -1; { if Head.IsOrdered then _MaxOrder := Head._Order - 1; }
411
procedure TTreeItem._InsertTail(const Child_: TTreeItem);
413
_Insert(Tail, Child_, _Zero);
415
{ if Tail.IsOrdered then _MaxOrder := Tail._Order; }
418
procedure TTreeItem._InsertPrev(const Sibli_: TTreeItem);
420
_Parent._Insert(_Prev, Sibli_, Self);
423
_Parent._MaxOrder := _Order - 1;
426
procedure TTreeItem._InsertNext(const Sibli_: TTreeItem);
428
_Parent._Insert(Self, Sibli_, _Next);
431
_Parent._MaxOrder := _Order;
434
// ------------------------------------------------------------------------------
436
procedure TTreeItem.InsertHead(const Child_: TTreeItem);
442
procedure TTreeItem.InsertTail(const Child_: TTreeItem);
448
procedure TTreeItem.InsertPrev(const Sibli_: TTreeItem);
454
procedure TTreeItem.InsertNext(const Sibli_: TTreeItem);
460
// ------------------------------------------------------------------------------
462
class procedure TTreeItem.Swap(const C1_, C2_: TTreeItem);
464
P1, P2, C1n, C1u, C2n, C2u: TTreeItem;
492
Bind(C1n, C2_, C1_, C2u)
493
else if C1_ = C2u then
494
Bind(C2n, C1_, C2_, C1u)
503
P1._Links[I1] := C2_;
509
P2._Links[I2] := C1_;
514
procedure TTreeItem.Swap(const I1_, I2_: Integer);
516
Swap(Childs[I1_], Childs[I2_]);
519
// ------------------------------------------------------------------------------
521
procedure TTreeItem.RunFamily(const Proc_: TNodeProc<TTreeItem>);
527
for I := 0 to ChildsN - 1 do
528
Childs[I].RunFamily(Proc_);