SDSL: Succinct Data Structure Library
A C++ template library for succinct data structures
 All Classes Namespaces Files Functions Variables Typedefs Friends
sdsl/include/sdsl/cst_iterators.hpp
Go to the documentation of this file.
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