SDSL: Succinct Data Structure Library
A C++ template library for succinct data structures
|
00001 /* sdsl - succinct data structures library 00002 Copyright (C) 2009 Simon Gog 00003 00004 This program is free software: you can redistribute it and/or modify 00005 it under the terms of the GNU General Public License as published by 00006 the Free Software Foundation, either version 3 of the License, or 00007 (at your option) any later version. 00008 00009 This program is distributed in the hope that it will be useful, 00010 but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 GNU General Public License for more details. 00013 00014 You should have received a copy of the GNU General Public License 00015 along with this program. If not, see http://www.gnu.org/licenses/ . 00016 */ 00021 #ifndef INCLUDED_SDSL_CST_ITERATORS 00022 #define INCLUDED_SDSL_CST_ITERATORS 00023 00024 namespace sdsl 00025 { 00026 00028 00047 // TODO: implement operator-- 00048 template<class Cst, uint32_t cache_size=128> 00049 class cst_dfs_const_forward_iterator: public std::iterator<std::forward_iterator_tag, typename Cst::node_type> 00050 { 00051 public: 00052 typedef typename Cst::node_type value_type; 00053 typedef const value_type const_reference; 00054 typedef typename Cst::size_type size_type; 00055 typedef cst_dfs_const_forward_iterator<Cst> iterator; 00056 typedef typename Cst::node_type node_type; 00057 private: 00058 const Cst* m_cst; 00059 node_type m_v; 00060 bool m_visited; 00061 bool m_valid; 00062 node_type* m_stack_cache; 00063 uint32_t m_stack_size; 00064 00065 00066 inline node_type parent() { 00067 --m_stack_size; // decrease stack size 00068 if (m_stack_cache != NULL and m_stack_size < cache_size) { 00069 return m_stack_cache[m_stack_size]; 00070 } else 00071 return m_cst->parent(m_v); 00072 } 00073 00074 inline node_type first_child() { 00075 if (m_stack_cache != NULL and m_stack_size < cache_size) // push node to the stack 00076 m_stack_cache[ m_stack_size ] = m_v; 00077 m_stack_size++; 00078 return m_cst->ith_child(m_v, 1); 00079 } 00080 00081 public: 00082 00084 cst_dfs_const_forward_iterator():m_cst(NULL),m_visited(false),m_valid(false), m_stack_cache(NULL) 00085 {} 00086 00088 cst_dfs_const_forward_iterator(const Cst* cst, const value_type node, bool visited=false, bool valid=true):m_visited(visited), m_valid(valid), m_stack_cache(NULL) { 00089 m_cst = cst; 00090 m_v = node; 00091 if (m_cst == NULL) { 00092 m_valid = false; 00093 } else if (node == m_cst->root() and !visited and valid) { // if the iterator equal cst.begin() 00094 m_stack_cache = new node_type[cache_size]; 00095 m_stack_size = 0; 00096 // std::cerr<<"#creating stack "<<m_cst->lb(m_v)<<" "<<m_cst->rb(m_v)<<std::endl; 00097 } 00098 } 00099 00101 // cst_dfs_const_forward_iterator(const cst_dfs_const_forward_iterator &it):m_cst(it.cst),m_v(it.m_v),m_valid(m_valid), m_stack_cache(NULL),m_stack_size(0){ 00102 // } 00103 00104 ~cst_dfs_const_forward_iterator() { 00105 if (m_stack_cache != NULL) { 00106 // std::cerr<<"#deleting stack "<<m_cst->lb(m_v)<<" "<<m_cst->rb(m_v)<<std::endl; 00107 delete [] m_stack_cache; 00108 } 00109 } 00110 00112 uint8_t visit()const { 00113 return 1+(uint8_t)m_visited; 00114 } 00115 00116 void skip_subtree() { 00117 if (m_valid) { 00118 if (!m_visited) { 00119 m_visited = true; 00120 } 00121 } 00122 } 00123 00125 const_reference operator*()const { 00126 return m_v; 00127 } 00128 00130 iterator& operator++() { 00131 if (!m_valid) 00132 return *this; 00133 if (m_v == m_cst->root() and m_visited) { 00134 m_valid = false; 00135 return *this; 00136 } 00137 value_type w; 00138 if (!m_visited) { // go down, if possible 00139 if (m_cst->is_leaf(m_v)) { 00140 w = m_cst->sibling(m_v); // determine sibling of leaf v 00141 if (w == m_cst->root()) { // if there exists no right sibling of the leaf v 00142 // w = m_cst->parent(m_v); 00143 w = parent(); 00144 m_visited = true; // go up 00145 } 00146 } else { // v is not a leaf => go down the tree 00147 w = first_child(); 00148 } 00149 } else { // 00150 w = m_cst->sibling(m_v); 00151 if (w == m_cst->root()) { // if there exists no rigth sibling 00152 w = parent(); 00153 } else { 00154 m_visited = false; 00155 } 00156 } 00157 m_v = w; 00158 return *this; 00159 } 00160 00162 void operator++(int x) { 00163 ++(*this); 00164 } 00165 00167 bool operator==(const iterator& it)const { 00168 return (it.m_visited == m_visited) // visited status is equal 00169 and (it.m_valid == m_valid) // valid status is equal => for end() iterator 00170 and (it.m_v == m_v) // nodes are equal 00171 and (it.m_cst == m_cst); // iterator belongs to the same cst 00172 } 00173 00175 bool operator!=(const iterator& it)const { 00176 return !(*this==it); 00177 } 00178 00179 }; 00180 00182 template<class Cst> 00183 class cst_bottom_up_const_forward_iterator: public std::iterator<std::forward_iterator_tag, typename Cst::node_type> 00184 { 00185 public: 00186 typedef typename Cst::node_type value_type; 00187 typedef const value_type const_reference; 00188 typedef typename Cst::size_type size_type; 00189 typedef cst_bottom_up_const_forward_iterator<Cst> iterator; 00190 private: 00191 const Cst* m_cst; 00192 typename Cst::node_type m_v; 00193 bool m_valid; 00194 public: 00195 00197 cst_bottom_up_const_forward_iterator():m_cst(NULL),m_valid(false) {} 00198 00200 cst_bottom_up_const_forward_iterator(const Cst* cst, const value_type node, bool valid=true):m_valid(valid) { 00201 m_cst = cst; 00202 m_v = node; 00203 if (m_cst == NULL) 00204 m_valid = false; 00205 } 00206 00208 const_reference operator*()const { 00209 return m_v; 00210 } 00211 00213 iterator& operator++() { 00214 if (!m_valid) 00215 return *this; 00216 if (m_v == m_cst->root()) { 00217 m_valid = false; 00218 return *this; 00219 } 00220 value_type w = m_cst->sibling(m_v); 00221 if (w == m_cst->root()) { // if no next right sibling exist 00222 m_v = m_cst->parent(m_v); // go to parent 00223 } else { // if next right sibling exist 00224 m_v = m_cst->leftmost_leaf_in_the_subtree(w); // go to leaftmost leaf in the subtree of w 00225 } 00226 return *this; 00227 } 00228 00230 iterator operator++(int x) { 00231 iterator it = *this; 00232 ++(*this); 00233 return it; 00234 } 00235 00237 bool operator==(const iterator& it)const { 00238 return (it.m_valid == m_valid) // valid status is equal => for end() iterator 00239 and (it.m_v == m_v) // nodes are equal 00240 and (it.m_cst == m_cst); // iterator belongs to the same cst 00241 } 00242 00244 bool operator!=(const iterator& it)const { 00245 return !(*this==it); 00246 } 00247 00248 }; 00249 00251 00256 template<class Cst, class Queue = std::queue<typename Cst::node_type> > 00257 class cst_bfs_iterator: public std::iterator<std::forward_iterator_tag, typename Cst::node_type> 00258 { 00259 public: 00260 typedef typename Cst::node_type value_type; 00261 typedef const value_type const_reference; 00262 typedef typename Cst::size_type size_type; 00263 typedef cst_bfs_iterator<Cst, Queue> iterator; 00264 typedef Queue queue_type; 00265 private: 00266 const Cst* m_cst; // Pointer to the cst. 00267 queue_type m_queue; // 00268 bool m_valid; // State of the iterator. 00269 00270 public: 00271 00273 00279 cst_bfs_iterator(const Cst* cst, const value_type node, bool valid=true, bool end_it=false) { 00280 m_cst = cst; 00281 m_valid = valid; 00282 if (m_cst != NULL and !end_it) { 00283 m_queue.push(node); 00284 } 00285 } 00286 00288 size_type size()const { 00289 return m_queue.size(); 00290 } 00291 00293 const_reference operator*()const { 00294 return m_queue.front(); 00295 } 00296 00298 iterator& operator++() { 00299 if (!m_valid) 00300 return *this; 00301 if (m_queue.empty()) { 00302 m_valid = false; 00303 return *this; 00304 } 00305 value_type v = m_queue.front(); 00306 m_queue.pop(); 00307 value_type child = m_cst->ith_child(v, 1); 00308 while (m_cst->root() != child) { 00309 m_queue.push(child); 00310 child = m_cst->sibling(child); 00311 } 00312 return *this; 00313 } 00314 00316 iterator operator++(int x) { 00317 iterator it = *this; 00318 ++(*this); 00319 return it; 00320 } 00321 00323 bool operator==(const iterator& it)const { 00324 if (m_queue.size() != it.m_queue.size()) { // if the queue size is different 00325 return false; // the state of the to iterator are different 00326 } 00327 if (m_queue.empty()) { // if the queue is empty, we have to check if they are valid and 00328 return it.m_valid == m_valid and it.m_cst == m_cst; // belong to the same cst 00329 } 00330 return (it.m_valid == m_valid) // valid status is equal => for end() iterator 00331 and (it.m_cst == m_cst) // iterator belongs to the same cst 00332 and (it.m_queue.front() == m_queue.front()) // front element and 00333 and (it.m_queue.back() == m_queue.back()); // back element are the same. 00334 } 00335 00337 bool operator!=(const iterator& it)const { 00338 return !(*this==it); 00339 } 00340 00341 }; 00342 00343 00344 } // end namespace sdsl 00345 00346 #endif