00001 #ifndef x_graphwalker_h
00002 #define x_graphwalker_h
00003
00004 #include "DetectorDescription/Core/interface/adjgraph.h"
00005
00006 #include <vector>
00007 #include <queue>
00008
00009
00010
00012 template <class N, class E>
00013 class graphwalker
00014 {
00015 public:
00016 typedef typename graph<N,E>::index_type index_type;
00017
00018 typedef typename graph<N,E>::index_result index_result;
00019
00020 typedef typename graph<N,E>::edge_type edge_type;
00021
00022 typedef typename graph<N,E>::edge_list edge_list;
00023
00024 typedef typename graph<N,E>::edge_iterator edge_iterator;
00025
00026 typedef typename graph<N,E>::const_edge_iterator const_edge_iterator;
00027
00028
00029 typedef typename std::pair<const_edge_iterator, const_edge_iterator> edge_range;
00030
00031
00032
00033 typedef std::vector<edge_range> stack_type;
00034 typedef std::queue<edge_type> bfs_type;
00035
00036 typedef bool result_type;
00037
00038 typedef typename graph<N,E>::value_type value_type;
00039
00040
00041 public:
00043 graphwalker(const graph<N,E> &);
00044
00046 graphwalker(const graph<N,E> &, const N & );
00047
00048
00049
00050 result_type firstChild();
00051
00052 result_type nextSibling();
00053
00054 result_type parent();
00055
00056 result_type next();
00057
00058 inline value_type current() const;
00059
00060 result_type next_bfs();
00061 value_type current_bfs() const;
00062
00063 void reset();
00064
00065 const stack_type & stack() const { return stack_;}
00066
00067 protected:
00068
00069 stack_type stack_;
00070 bfs_type queue_;
00071 edge_list root_;
00072
00073 const graph<N,E> & graph_;
00074
00075 private:
00076 graphwalker();
00077
00078 };
00079
00080
00081
00082 template<class N, class E>
00083 graphwalker<N,E>::graphwalker(const graph<N,E> & g)
00084 : graph_(g)
00085 {
00086 graph_.findRoots(root_);
00087 stack_.push_back(edge_range(root_.begin(),root_.end()));
00088 if (root_.size()) {
00089 queue_.push(root_[0]);
00090 }
00091 }
00092
00093
00094 template<class N, class E>
00095 graphwalker<N,E>::graphwalker(const graph<N,E> & g, const N & root)
00096 : graph_(g)
00097 {
00098 index_result rr = graph_.nodeIndex(root);
00099 if (!rr.second)
00100 throw root;
00101
00102 root_.push_back(edge_type(rr.first, 0));
00103 stack_.push_back(edge_range(root_.begin(),root_.end()));
00104 queue_.push(root_[0]);
00105 }
00106
00107
00108 template<class N, class E>
00109 typename graphwalker<N,E>::value_type graphwalker<N,E>::current() const
00110 {
00111 const edge_range & er = stack_.back();
00112
00113
00114
00115
00116
00117 return value_type(graph_.nodeData(er.first->first), graph_.edgeData(er.first->second));
00118 }
00119
00120
00121 template<class N, class E>
00122 typename graphwalker<N,E>::value_type graphwalker<N,E>::current_bfs() const
00123 {
00124 const edge_type & e = queue_.front();
00125 return value_type(graph_.nodeData(e.first), graph_.edgeData(e.second));
00126 }
00127
00128
00129 template<class N, class E>
00130 void graphwalker<N,E>::reset()
00131 {
00132
00133 stack_.clear();
00134 stack_.push_back(edge_range(root_.begin(),root_.end()));
00135 queue_.clear();
00136 if (root_.size()) {
00137 queue_.push(root_[0]);
00138 }
00139 }
00140
00141
00142 template<class N, class E>
00143 typename graphwalker<N,E>::result_type graphwalker<N,E>::firstChild()
00144 {
00145 result_type result = false;
00146 const edge_range & adjEdges
00147 = graph_.edges(stack_.back().first->first);
00148 if (adjEdges.first != adjEdges.second) {
00149 stack_.push_back(adjEdges);
00150 result = true;
00151 }
00152 return result;
00153 }
00154
00155
00156 template<class N, class E>
00157 typename graphwalker<N,E>::result_type graphwalker<N,E>::nextSibling()
00158 {
00159 result_type result = false;
00160
00161 edge_range & siblings = stack_.back();
00162 if (siblings.first != (siblings.second - 1) ) {
00163 ++siblings.first;
00164 result = true;
00165 }
00166
00167 return result;
00168 }
00169
00170
00171 template<class N, class E>
00172 typename graphwalker<N,E>::result_type graphwalker<N,E>::parent()
00173 {
00174
00175 result_type result = false;
00176 if (stack_.size()>1) {
00177 stack_.pop_back();
00178 result = true;
00179 }
00180 return result;
00181 }
00182
00183
00184 template<class N, class E>
00185 typename graphwalker<N,E>::result_type graphwalker<N,E>::next()
00186 {
00187 result_type result = false;
00188 if (firstChild()) {
00189 result = true;
00190 }
00191 else if(stack_.size()>1 && nextSibling()) {
00192 result = true;
00193 }
00194 else {
00195 while(parent()) {
00196 if(stack_.size()>1 && nextSibling()) {
00197 result = true;
00198 break;
00199 }
00200 }
00201 }
00202 return result;
00203 }
00204
00205 template<class N, class E>
00206 typename graphwalker<N,E>::result_type graphwalker<N,E>::next_bfs()
00207 {
00208 result_type result(false);
00209 if (!queue_.empty()) {
00210 const edge_type & e = queue_.front();
00211 const edge_range & er = graph_.edges(e.first);
00212 const_edge_iterator it(er.first), ed(er.second);
00213 for (; it != ed; ++it) {
00214 queue_.push(*it);
00215 }
00216 queue_.pop();
00217 if (!queue_.empty()) {
00218 result=true;
00219 }
00220 }
00221 return result;
00222 }
00223 #endif