30 const QVector<T *> &elements,
31 const QHash<T *, QVector<T *>> &successors)
33 QSet<T *> feedbackNodes;
36 QHash<T *, int> nodeIndex;
37 QHash<T *, int> lowlink;
46 for (
auto *element : elements) {
47 if (nodeIndex.contains(element)) {
51 QStack<Frame> callStack;
52 nodeIndex[element] = indexCounter;
53 lowlink[element] = indexCounter;
55 sccStack.push(element);
56 onStack.insert(element);
57 callStack.push({element, 0});
59 while (!callStack.isEmpty()) {
60 auto &frame = callStack.top();
63 const auto it = successors.constFind(node);
64 const int succCount = (it != successors.constEnd()) ?
static_cast<int>(it->size()) : 0;
66 if (frame.successorIdx < succCount) {
67 T *succ = (*it)[frame.successorIdx];
70 if (!nodeIndex.contains(succ)) {
71 nodeIndex[succ] = indexCounter;
72 lowlink[succ] = indexCounter;
76 callStack.push({succ, 0});
77 }
else if (onStack.contains(succ)) {
78 lowlink[node] = (std::min)(lowlink[node], nodeIndex[succ]);
82 if (lowlink[node] == nodeIndex[node]) {
92 for (
auto *n : std::as_const(scc)) {
93 feedbackNodes.insert(n);
95 }
else if ((it != successors.constEnd()) && it->contains(node)) {
96 feedbackNodes.insert(node);
102 if (!callStack.isEmpty()) {
103 T *parent = callStack.top().node;
104 lowlink[parent] = (std::min)(lowlink[parent], lowlink[node]);
110 return feedbackNodes;
225 const QVector<T *> &elements,
226 const QHash<T *, QVector<T *>> &successors,
227 QHash<T *, int> &outPriorities)
243 for (
auto *element : elements) {
244 if (outPriorities.contains(element)) {
251 while (!stack.isEmpty()) {
252 auto *current = stack.top();
254 if (outPriorities.contains(current)) {
259 const auto it = successors.constFind(current);
261 if (!expanded.contains(current)) {
262 expanded.insert(current);
263 if (it != successors.constEnd()) {
264 for (
auto *successor : *it) {
265 if (!outPriorities.contains(successor)) {
266 stack.push(successor);
273 int maxSuccessorPriority = 0;
274 if (it != successors.constEnd()) {
275 for (
auto *successor : *it) {
276 maxSuccessorPriority = (std::max)(maxSuccessorPriority, outPriorities.value(successor));
280 outPriorities[current] = maxSuccessorPriority + 1;
QSet< T * > findFeedbackNodes(const QVector< T * > &elements, const QHash< T *, QVector< T * > > &successors)
Finds all nodes that participate in feedback loops (cycles).
void calculatePriorities(const QVector< T * > &elements, const QHash< T *, QVector< T * > > &successors, QHash< T *, int > &outPriorities)
Priority calculation for directed graphs.
void legacyCalculatePriorities(const QVector< T * > &elements, const QHash< T *, QVector< T * > > &successors, QHash< T *, int > &outPriorities)
Legacy iterative DFS priority calculation, used for cyclic graphs only.