| 120 | |
| 121 | template <typename T> |
| 122 | void ReverseDFSFromHelper(const Graph& g, gtl::ArraySlice<T> start, |
| 123 | const std::function<void(T)>& enter, |
| 124 | const std::function<void(T)>& leave, |
| 125 | const NodeComparator& stable_comparator) { |
| 126 | // Stack of work to do. |
| 127 | struct Work { |
| 128 | T node; |
| 129 | bool leave; // Are we entering or leaving n? |
| 130 | }; |
| 131 | std::vector<Work> stack(start.size()); |
| 132 | for (int i = 0; i < start.size(); ++i) { |
| 133 | stack[i] = Work{start[i], false}; |
| 134 | } |
| 135 | |
| 136 | std::vector<bool> visited(g.num_node_ids(), false); |
| 137 | while (!stack.empty()) { |
| 138 | Work w = stack.back(); |
| 139 | stack.pop_back(); |
| 140 | |
| 141 | T n = w.node; |
| 142 | if (w.leave) { |
| 143 | leave(n); |
| 144 | continue; |
| 145 | } |
| 146 | |
| 147 | if (visited[n->id()]) continue; |
| 148 | visited[n->id()] = true; |
| 149 | if (enter) enter(n); |
| 150 | |
| 151 | // Arrange to call leave(n) when all done with descendants. |
| 152 | if (leave) stack.push_back(Work{n, true}); |
| 153 | |
| 154 | auto add_work = [&visited, &stack](T out) { |
| 155 | if (!visited[out->id()]) { |
| 156 | // Note; we must not mark as visited until we actually process it. |
| 157 | stack.push_back(Work{out, false}); |
| 158 | } |
| 159 | }; |
| 160 | |
| 161 | if (stable_comparator) { |
| 162 | std::vector<T> nodes_sorted; |
| 163 | for (const Edge* in_edge : n->in_edges()) { |
| 164 | nodes_sorted.emplace_back(in_edge->src()); |
| 165 | } |
| 166 | std::sort(nodes_sorted.begin(), nodes_sorted.end(), stable_comparator); |
| 167 | for (T in : nodes_sorted) { |
| 168 | add_work(in); |
| 169 | } |
| 170 | } else { |
| 171 | for (const Edge* in_edge : n->in_edges()) { |
| 172 | add_work(in_edge->src()); |
| 173 | } |
| 174 | } |
| 175 | } |
| 176 | } |
| 177 | |
| 178 | } // namespace |
| 179 |
no test coverage detected