/packages/fcl-stl/src/gtree.pp

https://github.com/slibre/freepascal · Puppet · 139 lines · 114 code · 25 blank · 0 comment · 8 complexity · 7fdcbb651f6cfff9fff83dd58441f80e MD5 · raw file

  1. {
  2. This file is part of the Free Pascal FCL library.
  3. Copyright 2013 Mario Ray Mahardhika
  4. Implements a generic Tree.
  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. unit gtree;
  12. {$mode objfpc}{$H+}
  13. interface
  14. uses
  15. gvector,gstack,gqueue;
  16. type
  17. { TTreeNode }
  18. generic TTreeNode<T> = class
  19. public type
  20. TTreeNodeList = specialize TVector<TTreeNode>;
  21. protected
  22. FData: T;
  23. FChildren: TTreeNodeList;
  24. public
  25. constructor Create;
  26. constructor Create(const AData: T);
  27. destructor Destroy; override;
  28. property Data: T read FData write FData;
  29. property Children: TTreeNodeList read FChildren;
  30. end;
  31. generic TDepthFirstCallback<T> = procedure (const AData: T);
  32. generic TBreadthFirstCallback<T> = procedure (const AData: T);
  33. generic TTree<T> = class
  34. public type
  35. TTreeNodeType = specialize TTreeNode<T>;
  36. TDepthFirstCallbackType = specialize TDepthFirstCallback<T>;
  37. TBreadthFirstCallbackType = specialize TBreadthFirstCallback<T>;
  38. private type
  39. type
  40. TStackType = specialize TStack<TTreeNodeType>;
  41. TQueueType = specialize TQueue<TTreeNodeType>;
  42. private
  43. FRoot: TTreeNodeType;
  44. public
  45. constructor Create;
  46. destructor Destroy; override;
  47. procedure DepthFirstTraverse(Callback: TDepthFirstCallbackType);
  48. procedure BreadthFirstTraverse(Callback: TBreadthFirstCallbackType);
  49. property Root: TTreeNodeType read FRoot write FRoot;
  50. end;
  51. implementation
  52. { TTreeNode }
  53. constructor TTreeNode.Create;
  54. begin
  55. FChildren := TTreeNodeList.Create;
  56. end;
  57. constructor TTreeNode.Create(const AData: T);
  58. begin
  59. FData := AData;
  60. FChildren := TTreeNodeList.Create;
  61. end;
  62. destructor TTreeNode.Destroy;
  63. var
  64. Child: TTreeNode;
  65. begin
  66. for Child in FChildren do begin
  67. Child.Free;
  68. end;
  69. FChildren.Free;
  70. end;
  71. { TTree }
  72. constructor TTree.Create;
  73. begin
  74. FRoot := nil;
  75. end;
  76. destructor TTree.Destroy;
  77. begin
  78. FRoot.Free;
  79. end;
  80. procedure TTree.DepthFirstTraverse(Callback: TDepthFirstCallbackType);
  81. var
  82. Stack: TStackType;
  83. Node,Child: TTreeNodeType;
  84. begin
  85. if Assigned(FRoot) then begin
  86. Stack := TStackType.Create;
  87. Stack.Push(FRoot);
  88. while Stack.Size > 0 do begin
  89. Node := Stack.Top;
  90. Stack.Pop;
  91. Callback(Node.Data);
  92. for Child in Node.Children do Stack.Push(Child);
  93. end;
  94. Stack.Free;
  95. end;
  96. end;
  97. procedure TTree.BreadthFirstTraverse(Callback: TBreadthFirstCallbackType);
  98. var
  99. Queue: TQueueType;
  100. Node,Child: TTreeNodeType;
  101. begin
  102. if Assigned(FRoot) then begin
  103. Queue := TQueueType.Create;
  104. Queue.Push(FRoot);
  105. while Queue.Size > 0 do begin
  106. Node := Queue.Front;
  107. Queue.Pop;
  108. Callback(Node.Data);
  109. for Child in Node.Children do Queue.Push(Child);
  110. end;
  111. Queue.Free;
  112. end;
  113. end;
  114. end.