OpenShaderDesigner 0.0.1
Loading...
Searching...
No Matches
DirectedGraph.h
1// =====================================================================================================================
2// Copyright 2024 Medusa Slockbower
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14// =====================================================================================================================
15
16#ifndef DIRECTEDGRAPH_H
17#define DIRECTEDGRAPH_H
18
19#include <deque>
20#include <vector>
21
22template<typename T>
24{
25public:
26 // Typedefs ========================================================================================================
27
28 using DataType = T;
29 using Node = uint32_t;
30 using NodeQueue = std::deque<Node>;
31
32private:
33 // Data Structures =================================================================================================
34
35 struct Director
36 {
37 enum Flags
38 {
39 VALID = 0b00000000000000000000000000000001
40 };
41
42 Node Parent, Child, Sibling;
43 uint32_t Flags;
44
45 Director() : Parent(0), Child(0), Sibling(0), Flags(VALID) { }
46 };
47
48 using Hierarchy = std::vector<Director>;
49 using Storage = std::vector<DataType>;
50
51public:
52 // Functions =======================================================================================================
53
54 DirectedGraph() : Graph{ Director() }, Data{ DataType() }, Freed{ } { }
55
56 [[nodiscard]] Node Parent(Node node) const { return Graph[node].Parent; }
57 [[nodiscard]] Node FirstChild(Node node) const { return Graph[node].Child; }
58 [[nodiscard]] Node NextSibling(Node node) const { return Graph[node].Sibling; }
59
60 [[nodiscard]] Node LeftMost(Node node) const
61 {
62 Node current = node;
63 while(node = FirstChild(current)) current = node;
64 return current;
65 }
66
67 [[nodiscard]] uint32_t Depth(Node node) const
68 {
69 uint32_t depth = 0;
70 while (node)
71 {
72 node = Parent(node);
73 ++depth;
74 }
75 return depth;
76 }
77
78 Node Insert(const DataType& data, Node parent)
79 {
80 if(Freed.empty())
81 {
82 Freed.push_back(static_cast<Node>(Graph.size()));
83 Graph.push_back(Director()); Data.push_back(DataType());
84 }
85
86 Node next = Freed.front(); Freed.pop_front();
87 Director& pnode = Graph[parent];
88 Director& node = Graph[next];
89
90 // Setup Node
91 node.Parent = parent;
92 node.Sibling = pnode.Child;
93 node.Child = 0;
94 node.Flags = Director::VALID;
95
96 // Set parent's child
97 pnode.Child = next;
98
99 Data[next] = data;
100
101 return next;
102 }
103
104 void Erase(Node node)
105 {
106 if(node == 0) return;
107
108 Director& erased = Graph[node];
109 erased.Flags &= ~Director::VALID;
110 Freed.push_back(node);
111
112 Graph[erased.Parent].Child = erased.Sibling;
113
114 NodeQueue stack{ erased.Child };
115
116 while(stack.empty() == false)
117 {
118 Node next = stack.front(); stack.pop_front();
119 Director& child = Graph[next];
120 child.Flags &= ~Director::VALID;
121 Freed.push_back(next);
122
123 if(child.Sibling) stack.push_front(child.Sibling);
124 if(child.Child) stack.push_front(child.Child);
125 }
126 }
127
128 DataType& operator[](Node node) { return Data[node]; }
129 [[nodiscard]] const DataType& operator[](Node node) const { return Data[node]; }
130
131 template<typename V, typename O>
132 void Traverse(V& visitor)
133 {
134 Traverser<V, O> traverser(*this, visitor);
135 traverser();
136 }
137
138private:
139 // Variables =======================================================================================================
140
141 Hierarchy Graph;
142 Storage Data;
143 NodeQueue Freed;
144
145public:
146 // Navigation ======================================================================================================
147
148 friend class BreadthFirst;
150 {
151 public:
152 BreadthFirst(DirectedGraph& graph) : Graph(graph), VisitQueue(0) { }
153
154 Node operator()(Node node)
155 {
156 node = VisitQueue.back(); VisitQueue.pop_back();
157 Director& current = Graph.Graph[node];
158
159 if(current.Sibling) VisitQueue.push_back(current.Sibling);
160 if(current.Child) VisitQueue.push_front(current.Child);
161
162 if(VisitQueue.empty()) return 0;
163 return node;
164 }
165
166 private:
167 DirectedGraph& Graph;
168 NodeQueue VisitQueue;
169 };
170
171 friend class PreOrder;
173 {
174 public:
175 PreOrder(DirectedGraph& graph) : Graph(graph) { }
176
177 Node operator()(Node node)
178 {
179 Director& current = Graph.Graph[node];
180
181 if(current.Sibling) VisitQueue.push_front(current.Sibling);
182 if(current.Child) VisitQueue.push_front(current.Child);
183
184 if(VisitQueue.empty()) return 0;
185 Node next = VisitQueue.front(); VisitQueue.pop_front();
186 return next;
187 }
188
189 private:
190 DirectedGraph& Graph;
191 NodeQueue VisitQueue;
192 };
193
194 friend class InOrder;
196 {
197 public:
198 InOrder(DirectedGraph& graph) : Graph(graph) { }
199
200 Node operator()(Node node)
201 {
202 if(node == 0) VisitQueue.push_back(Graph.LeftMost(node));
203
204 node = VisitQueue.front(); VisitQueue.pop_front();
205 Director& current = Graph.Graph[node];
206
207 if(current.Sibling)
208 {
209 if(Graph.NextSibling(current.Sibling)) VisitQueue.push_back(current.Parent);
210 VisitQueue.push_back(Graph.LeftMost(current.Sibling));
211 }
212
213 return node;
214 }
215
216 private:
217 DirectedGraph& Graph;
218 NodeQueue VisitQueue;
219 };
220
221 friend class PostOrder;
223 {
224 public:
225 PostOrder(DirectedGraph& graph) : Graph(graph) { }
226
227 Node operator()(Node node)
228 {
229 if(VisitQueue.empty()) VisitQueue.push_back(Graph.LeftMost(node));
230
231 node = VisitQueue.front(); VisitQueue.pop_front();
232 if(node == 0) return node;
233 Director& current = Graph.Graph[node];
234
235 VisitQueue.push_back(current.Sibling ? Graph.LeftMost(current.Sibling) : Graph.Parent(node));
236
237 return node;
238 }
239
240 private:
241 DirectedGraph& Graph;
242 NodeQueue VisitQueue;
243 };
244
245 template<typename V, typename O>
247 {
248 public:
249 using VisitorType = V;
250 using OrderType = O;
251
252 Traverser(DirectedGraph& graph, VisitorType& visitor) : Graph(graph), Visitor(visitor), Order(graph) { }
253
254 void operator()()
255 {
256 Node node = 0;
257 while(node = Order(node))
258 {
259 if(Visitor(Graph[node], node)) break;
260 }
261 }
262
263 private:
264 DirectedGraph& Graph;
265 VisitorType& Visitor;
266 OrderType Order;
267 };
268};
269
270#endif //DIRECTEDGRAPH_H
Definition DirectedGraph.h:150
Definition DirectedGraph.h:196
Definition DirectedGraph.h:223
Definition DirectedGraph.h:173
Definition DirectedGraph.h:247
Definition DirectedGraph.h:24