Boost logo

Boost-Commit :

From: chintanraoh_at_[hidden]
Date: 2008-06-20 14:45:32


Author: chintanraoh
Date: 2008-06-20 14:45:31 EDT (Fri, 20 Jun 2008)
New Revision: 46569
URL: http://svn.boost.org/trac/boost/changeset/46569

Log:
upper bound and lower bound
Text files modified:
   sandbox/SOC/2008/digital_searching/dsearch/boost/dsearch/patricia.hpp | 347 ++++++++++++++++++++++++---------------
   1 files changed, 211 insertions(+), 136 deletions(-)

Modified: sandbox/SOC/2008/digital_searching/dsearch/boost/dsearch/patricia.hpp
==============================================================================
--- sandbox/SOC/2008/digital_searching/dsearch/boost/dsearch/patricia.hpp (original)
+++ sandbox/SOC/2008/digital_searching/dsearch/boost/dsearch/patricia.hpp 2008-06-20 14:45:31 EDT (Fri, 20 Jun 2008)
@@ -22,8 +22,7 @@
 template<class Key,class Mapped,class Key_traits,class Alloc=std::allocator<char> >
 class patricia{
         private:
- template<class V_t, class N_t, class A>
- friend class patricia_iterator;
+
         typedef patricia<Key,Mapped,Key_traits,Alloc> self;
         typedef typename Key_traits::const_iterator key_iterator;
         typedef typename Key_traits::element_type key_element_type;
@@ -53,21 +52,25 @@
                 patricia_node(): par(0), index(0), left(0), right(0)
                 {
                 }
+
                 patricia_node(const key_type& key_,const std::size_t &index_,patricia_node *left_
                 ,patricia_node *right_,patricia_node *par_)
                 :par(par_),value(make_pair(key_,0)),index(index_),left(left_),right(right_)
                 {
                 }
+
                 patricia_node(const patricia_node &other)
                 :par(0),value(other.value),index(other.index),left(0),right(0)
                 {
                 }
         };
+
         typedef typename Alloc::template rebind<patricia_node>::other node_allocator_type;
         node_allocator_type node_allocator;
         patricia_node *root;
 
         public:
+
         typedef patricia_iterator<value_type, patricia_node, Alloc> iterator;
         typedef patricia_iterator<const value_type, const patricia_node, Alloc> const_iterator;
         typedef patricia_reverse_iterator<value_type, patricia_node, Alloc> reverse_iterator;
@@ -91,6 +94,12 @@
                 #endif
         }
 
+ self operator = (const self& other)
+ {
+ this->clear();
+ copy_patricia(other.root);
+ return *this;
+ }
         void insert(const value_type &v)
         {
                 this->operator [](v.first)=v.second;
@@ -166,6 +175,20 @@
         {
                 return const_cast<patricia *>(this)->find(k);
         }
+
+ iterator upper_bound(const key_type &k)
+ {
+ #ifndef FORWARD
+ return upper_bound(k,iterator_cat());
+ #else
+ return upper_bound(k,0);
+ #endif
+ }
+
+ const_iterator upper_bound(const key_type &k) const
+ {
+ return const_cast<patricia *>(this)->upper_bound(k);
+ }
 
         void erase(const key_type &k)
         {
@@ -265,73 +288,31 @@
         }
 
         private:
- //function for Random Access Iterator
- inline data_type &insert_new_node(const key_type &key,rand_tag)
+ /*
+ * gets node pair b/w which a key is to inserted
+ * also returns a pair of index and bit value of the key at that index
+ */
+ inline std::pair< std::pair<patricia_node*,patricia_node*>,
+ std::pair<std::size_t,int> >
+ get_insert_pair(const key_type &key,rand_tag)
         {
                 key_iterator it,end_it;
- patricia_node *cur=root,*next=root,*temp_node,*old_root=0;
+ patricia_node *cur=root,*next=root;
                 std::size_t pos=0;
-
- //std::cout<<"in random access"<<std::endl;
-
+ std::pair<patricia_node*,patricia_node*> node_pair;
                 std::pair<std::size_t,int> common;
-
- //std::cout<<"\nInserting \""<<key<<"\""<<std::endl;
+ const std::size_t key_size=Key_traits::size(key);
                 
                 it=Key_traits::begin(key);
                 end_it=Key_traits::end(key);
-
- const std::size_t key_size=Key_traits::size(key);
-
- //do some jugglery to ensure that inserting "" first as root wont cause any problems
- //move root to the right position while inserting the second
- //that will take care of the assert(next) in find
- old_root=0;
- if(root!=0 && root->left==root)
- {
- if(it==end_it) return root->value.second; //if one adds "" twice
- old_root=root;
- root=0;
- }
-
- if(root==0)
- {
- root=node_allocator.allocate(1);
- if(it!=end_it)
- {
- new(root) patricia_node( key, 0, old_root, root, 0 );
- if(old_root)
- {
- std::cout<<"assigning OLD ROOT"<<std::endl;
- old_root->par=root;
- }
- }
- else
- new(root) patricia_node( key, 0, root, 0, 0 );
-
- return root->value.second;
- }
                 
- if(it==end_it) //"" inserted
- {
- if(root->left!=0)
- next=root->left;
- else
- {
- root->left = node_allocator.allocate(1);
- new(root->left) patricia_node(key,0,root->left,0,root);
- return root->left->value.second;
- }
- }
 
- next=find_node(root,key,iterator_cat(),key_size);
+ node_pair=find_node_prev(root,key,iterator_cat(),key_size);
 
+ next=node_pair.first;
                 common=get_common_bits(key,next->value.first );
                 if ( common.second==2 )
- {
- std::cout<<"The key \""<<key<<"\" already exists"<<std::endl;
- return next->value.second;
- }
+ return std::make_pair(node_pair, common);
 
                 next=cur=root;
                 while (next->index < common.first) {
@@ -342,36 +323,77 @@
                         cur->right: cur->left;
                         if(cur->index >= next->index) break;
                 }
- temp_node=node_allocator.allocate(1);
                 
- if(cur->left==next) cur->left=temp_node;
- else
- if(cur->right==next)
- cur->right=temp_node;
- else
- assert(false);
+ return std::make_pair(std::make_pair(next,cur), common);
+ }
 
- assert(common.second!=2);
+ template<class T>
+ inline std::pair< std::pair<patricia_node*,patricia_node*>,
+ std::pair<std::size_t,int> >
+ get_insert_pair (const key_type &key,T)
+ {
+ key_iterator it,end_it;
+ key_element_type temp_element;
+ patricia_node *cur=root,*next=root;
+ std::size_t pos=0;
+ std::pair<std::size_t,int> common;
                 
- if(common.second) //temp_node should point to inself at 1 ie right
- new (temp_node) patricia_node(key,common.first,next,temp_node,cur);
- else
- new (temp_node) patricia_node(key,common.first,temp_node,next,cur);
+ it=Key_traits::begin(key);
+ end_it=Key_traits::end(key);
+
+ next=find_node(root,key,T());
+
+ //find the largerst prefix matching the key and the found key
+ //std::cout<<"After find"<<std::endl;
+ common=get_common_bits(key,next->value.first);
+
+ //key already exists
+ if(common.second==2)
+ return std::make_pair(std::make_pair(next,next),common);
 
- assert(root->par==0);
- if(cur->index < next->index) next->par=temp_node;
-
- assert(root->par==0);
- return temp_node->value.second;
+ //assert(common.first);wrong assert
+
+ //find the parent and child in between which this thing needs to be added.
+ //note: parent can be equal to child
+ //cur=parent, next=child
+ it=Key_traits::begin(key);
+ cur=root;
+ while(it!=end_it)
+ {
+ if ( (cur->index)%(bit_width+1)==0 )
+ next=cur->right;
+ else
+ {
+ temp_element=Key_traits::get_element(it);
+ next=get_nth_bit(temp_element,(cur->index)%(bit_width+1))?
+ cur->right:cur->left;
+ }
+
+ //fortunately in this case; this should happen only when it==end_it occures.
+ assert(next);
+ if ( next->index+1 > common.first ) break; //insert at cur using next->value->first
+ if ( next->index <= cur->index ) break;
+
+ while( pos < (next->index)/(bit_width+1) && it!=end_it )
+ {
+ ++pos;
+ ++it;
+ }
+ cur=next;
+ }
+ return std::make_pair(std::make_pair(next,cur),common);
         }
 
+ /*
+ * function for Random Access Iterator
+ */
         template<class T>
- inline data_type &insert_new_node(const key_type&key,T)
+ inline data_type &insert_new_node(const key_type &key,T)
         {
                 key_iterator it,end_it;
- key_element_type temp_element;
                 patricia_node *cur=root,*next=root,*temp_node,*old_root=0;
- std::size_t pos=0;
+ std::pair< std::pair<patricia_node*,patricia_node*>,
+ std::pair<std::size_t,int> > insert_pair;
                 
                 //std::cout<<"in random access"<<std::endl;
                 
@@ -381,7 +403,7 @@
                 
                 it=Key_traits::begin(key);
                 end_it=Key_traits::end(key);
-
+
                 //do some jugglery to ensure that inserting "" first as root wont cause any problems
                 //move root to the right position while inserting the second
                 //that will take care of the assert(next) in find
@@ -407,65 +429,31 @@
                         }
                         else
                                 new(root) patricia_node( key, 0, root, 0, 0 );
+
                         return root->value.second;
                 }
                 
                 if(it==end_it) //"" inserted
                 {
- if(root->left!=0)
- next=root->left;
- else
+ if(root->left==0)
                         {
                                 root->left = node_allocator.allocate(1);
                                 new(root->left) patricia_node(key,0,root->left,0,root);
- return root->left->value.second;
                         }
+ return root->left->value.second;
                 }
 
- next=find_node(root,key,T());
+ insert_pair=get_insert_pair(key,T());
                 
- //find the largerst prefix matching the key and the found key
- //std::cout<<"After find"<<std::endl;
- common=get_common_bits(key,next->value.first);
-
- //key already exists
- if(common.second==2)
+ common=insert_pair.second;
+ next=insert_pair.first.first;
+ cur=insert_pair.first.second;
+ if(common.second==2)
                 {
                         std::cout<<"The key \""<<key<<"\" already exists"<<std::endl;
                         return next->value.second;
                 }
-
- //assert(common.first);wrong assert
-
- //find the parent and child in between which this thing needs to be added.
- //note: parent can be equal to child
- //cur=parent, next=child
- it=Key_traits::begin(key);
- cur=root;
- while(it!=end_it)
- {
- if ( (cur->index)%(bit_width+1)==0 )
- next=cur->right;
- else
- {
- temp_element=Key_traits::get_element(it);
- next=get_nth_bit(temp_element,(cur->index)%(bit_width+1))?
- cur->right:cur->left;
- }
-
- //fortunately in this case; this should happen only when it==end_it occures.
- assert(next);
- if ( next->index+1 > common.first ) break; //insert at cur using next->value->first
- if ( next->index <= cur->index ) break;
-
- while( pos < (next->index)/(bit_width+1) && it!=end_it )
- {
- ++pos;
- ++it;
- }
- cur=next;
- }
-
+
                 temp_node=node_allocator.allocate(1);
                 
                 if(cur->left==next) cur->left=temp_node;
@@ -475,8 +463,6 @@
                 else
                         assert(false);
 
- assert(common.second!=2);
-
                 if(common.second) //temp_node should point to inself at 1 ie right
                         new (temp_node) patricia_node(key,common.first,next,temp_node,cur);
                 else
@@ -494,7 +480,8 @@
                 return n==0? 1 : ( ( element&(1<<(bit_width - n )) ) !=0 );
         }
 
- /* returns inclusive of end bit after each pos and the not(un) common bit in k1;
+ /*
+ * returns inclusive of end bit after each pos and the not(un) common bit in k1;
          * returns not common bit as two if both keys are equal.
          */
         inline std::pair<std::size_t,int> get_common_bits(const key_type &k1,const key_type &k2) const
@@ -597,7 +584,6 @@
                 }
                 return ret_it;
         }*/
-
         patricia_node* find_node(const patricia_node *cur, const key_type &key,rand_tag,std::size_t key_size=0)
         {
                 patricia_node *next=0;
@@ -606,26 +592,31 @@
                 std::size_t pos=0;
                 if(key_size==0)
                         key_size=key.size();
-
- if(root==0) return 0;
                 
- while ( pos < (cur->index)/(bit_width+1) && it!=end_it ) {
+ if ( root==0 ) return 0;
+
+ while ( pos < (cur->index)/(bit_width+1) && it!=end_it )
+ {
                         ++pos;
                         ++it;
                 }
- while (true ) {
+
+ while (true )
+ {
                         pos= cur->index / (bit_width + 1);
                         if ( pos >= key_size ) break;
+ std::cout<<"getting "<<cur->index<<"th bit of "<<key<<std::endl;
                         next=get_nth_bit ( Key_traits::get_element(it + pos), cur->index % (bit_width + 1) )?
                         cur->right: cur->left;
- //std::cout<<"In find: cur="<<cur->value.first
- //<<" going to next \""<<next->value.first<<"\""<<std::endl;
                         if(next==0) return 0;
+ std::cout<<"In find of "<<key<<": cur="<<cur->value.first
+ <<" going to next \""<<next->value.first<<"\""<<std::endl;
                         if(cur->index >= next->index) break;
                         cur=next;
                 }
 
- if(pos == key_size ) {
+ if (pos == key_size )
+ {
                         next=cur->left;
                 }
 
@@ -668,7 +659,7 @@
 
         template<class T>
         std::pair<patricia_node*,patricia_node*>
- find_node_prev(patricia_node *root, const key_type &key, T ,std::size_t)
+ find_node_prev(patricia_node *root, const key_type &key, T ,std::size_t=std::size_t())
         {
                 patricia_node *cur=root,*next;
                 std::size_t pos=0;
@@ -713,7 +704,8 @@
                 return std::make_pair(next,cur);
         }
 
- /* The node pointed to by found. where prev is the found
+ /*
+ * The node pointed to by found. where prev is the found
          * has a uplink from prev.
          * Used by erase(key) and erase(iterator);
          */
@@ -816,7 +808,9 @@
                 node_allocator.deallocate(found,1);
         }
 
- //used by erase(key);
+ /*
+ * used by erase(key);
+ */
         void inline copy_node_ptr(patricia_node* to, patricia_node* found)
         {
                 if(found->par!=0) {
@@ -842,6 +836,85 @@
                 to->index=found->index;
         }
 
+ template<class T>
+ iterator lower_bound(const key_type &key,T)
+ {
+ typedef std::pair<patricia_node*,patricia_node*> node_pair_type;
+ typedef std::pair<std::size_t, int> common_type;
+
+ std::pair<node_pair_type,common_type> node_pair;
+ common_type common;
+ patricia_node* next,cur;
+ iterator it;
+
+
+ if(root==0) return end();
+
+ if(root->right==0)
+ {
+ //is there is any lower bound it has to be ""
+ return begin();
+ }
+
+ node_pair=get_insert_pair(key,T());
+ next=node_pair.first.first;
+ cur =node_pair.first.second;
+ common=node_pair.second;
+
+ if(common.second==2) //key aleardy exists
+ return iterator(next,cur);
+
+ if(common.second==0)
+ return --iterator(next,cur);
+
+ assert(common.second==1);
+
+ it=iterator(next,cur);
+ it.to_right_most();
+ return it;
+ }
+
+ template<class T>
+ inline iterator upper_bound(const key_type &key,T)
+ {
+ typedef std::pair<patricia_node*,patricia_node*> node_pair_type;
+ typedef std::pair<std::size_t, int> common_type;
+
+ std::pair<node_pair_type,common_type> node_pair;
+ common_type common;
+ patricia_node* next,* cur;
+ iterator it;
+
+ if ( root==0 ) return end();
+
+ if ( root->right==0 )
+ {
+ if(Key_traits::begin(key)!=Key_traits::end(key) )
+ return end();
+ else
+ return begin();
+ }
+
+ node_pair=get_insert_pair(key,T());
+ next=node_pair.first.first;
+ cur =node_pair.first.second;
+ common=node_pair.second;
+ std::cout<<"Upper Bound:SECOND: "<<common.second<<std::endl;
+ switch ( common.second )
+ {
+ case 2://key aleardy exists
+ return iterator(next,cur);
+ case 1:
+ return ++iterator(next,cur);
+ case 0:
+ it=iterator(next,cur);
+ std::cout<<next->value.first<<"<-"<<cur->value.first<<std::endl;
+ it.to_left_most();
+ return it;
+ }
+ assert(false);
+ }
+
         //used by copy_patricia
         patricia_node *copy_patricia_find_par(patricia_node* const &this_cur,
         const patricia_node* const &other_cur,const patricia_node * const &par)
@@ -924,9 +997,11 @@
                         }
                 }
         }
-
 };
 
+/*
+ * TODO: implement O(n) time algo for this
+ */
 template<class Key,class Mapped,class Key_traits,class Alloc >
 bool operator == (const patricia<Key,Mapped,Key_traits,Alloc> & p1,
         const patricia<Key,Mapped,Key_traits,Alloc>& p2)


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk