Skip to content

Commit

Permalink
Reworked lower_bound implementation witout stack
Browse files Browse the repository at this point in the history
Implemented upper_bound in terms of lower_bound
Changed lower_bound an upper_bound return type to iterator instead of
node_ptr
  • Loading branch information
cosminBoaca committed Dec 19, 2015
1 parent e171cc1 commit 9ffbed8
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 66 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ tags
*.obj
*.exe
Jamroot
*a.out*

libs/
build/
Expand Down
114 changes: 48 additions & 66 deletions include/boost/trie/trie.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -526,93 +526,75 @@ class trie {

// upper_bound() to find the first node that greater than the key
template<typename Iter>
node_ptr upper_bound(Iter first, Iter last)
iterator upper_bound(Iter first, Iter last)
{
node_ptr cur = const_cast<node_ptr>(&root);
// use a stack to store iterator in order to avoid the iterator cannot go backward
std::stack< Iter > si;
for (; first != last; ++first)
{
si.push(first);
const key_type& cur_key = *first;
typename node_type::children_iter ci = cur->children.find(cur_key, node_comparator);
// using upper_bound needs comparison in every step, so using find until ci == NULL
if (ci == cur->children.end())
{
// find a node that
ci = cur->children.upper_bound(cur_key, node_comparator);
si.pop();
while (ci == cur->children.end())
{
if (cur->parent == NULL)
return &root;
cur = cur->parent;
ci = cur->children.upper_bound(*si.top());
}
cur = ci->second;
while (cur->no_value())
{
cur = &(*(cur->children.begin()));
}
return cur;
}
cur = &(*ci);
std::pair<iterator, bool> lb_result = lower_bound(first, last);
// Full match
if (lb_result.second) {
++lb_result.first;
}
// if find a full match, then increment it
iterator tmp(cur);
tmp.trie_node_increment();
cur = tmp.tnode;
return cur;
return lb_result.first;
}

template<typename Container>
node_ptr upper_bound(const Container &container)
iterator upper_bound(const Container &container)
{
return upper_bound(container.begin(), container.end());
}

// lower_bound()
template<typename Iter>
node_ptr lower_bound(Iter first, Iter last)
std::pair<iterator, bool> lower_bound(Iter first, Iter last)
{
node_ptr cur = const_cast<node_ptr>(&root);
// use a stack to store iterator in order to avoid the iterator cannot go backward
std::stack< Iter > si;
typedef typename node_type::children_iter children_iterator;
node_ptr cur = &root;
node_ptr last_lb_candidate = NULL;

for (; first != last; ++first)
{
si.push(first);
const key_type& cur_key = *first;
typename node_type::children_iter ci = cur->children.find(cur_key);
// using upper_bound needs comparison in every step, so using find until ci == NULL
if (ci == cur->children.end())
{
// find a node that
ci = cur->children.upper_bound(cur_key);
si.pop();
while (ci == cur->children.end())
{
if (cur->parent == NULL)
return &root;
cur = cur->parent;
ci = cur->children.upper_bound(*si.top());
}
cur = ci->second;
while (cur->no_value())
{
cur = &(*(cur->children.begin()));
children_iterator child_iter =
cur->children.find(cur_key, node_comparator);
if (child_iter == cur->children.end()) {
break;
}
children_iterator lb_candidate_iter = child_iter;
lb_candidate_iter++;
if (lb_candidate_iter != cur->children.end()) {
last_lb_candidate = &(*lb_candidate_iter);
}
cur = &(*child_iter);
}

if (first != last) {
children_iterator lb_candidate_iter =
cur->children.upper_bound(*first, node_comparator);
if (lb_candidate_iter == cur->children.end()) {
if (last_lb_candidate != NULL) {
cur = last_lb_candidate;
} else {
return std::make_pair(&root, false);
}
return cur;
} else {
return std::make_pair(&(*lb_candidate_iter), false);
}
cur = &(*ci);
}
// lower_bound() needn't increment here!!!
return cur;

if (!cur->no_value() && first == last) {
return std::make_pair(cur, true);
}

while (cur->no_value()) {
cur = &(*cur->children.begin());
}

return std::make_pair(cur, false);
}

template<typename Container>
node_ptr lower_bound(const Container &container)
iterator lower_bound(const Container &container)
{
return lower_bound(container.begin(), container.end());
return lower_bound(container.begin(), container.end()).first;
}

// equal_range() is the same as find_prefix? the meaning is different
Expand Down Expand Up @@ -778,7 +760,7 @@ class trie {
erase_node(cur);
}

void swap(const trie_type& t)
void swap(trie_type& t)
{
// is it OK?
std::swap(root, t.root);
Expand Down
35 changes: 35 additions & 0 deletions test/set.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -184,11 +184,46 @@ void iterator_operator_minus()
BOOST_TEST(riter == t.rbegin());
}

void lower_bound_test() {
tsci t;
std::string s1 = "aaa", s2 = "aab", s3 = "abc";
t.insert(s1);
t.insert(s2);
t.insert(s3);
BOOST_TEST(t.lower_bound(s1) == t.find(s1));
BOOST_TEST(t.lower_bound(std::string("abb")) == t.find(std::string("abc")));
BOOST_TEST(t.lower_bound(std::string("b")) == t.end());
t.insert(std::string("abcdef"));
BOOST_TEST(t.lower_bound(std::string("abcd")) == t.find(std::string("abcdef")));
t.insert(std::string("bbcccc"));
t.insert(std::string("bbd"));
BOOST_TEST(t.lower_bound(std::string("bbcccd")) == t.find(std::string("bbd")));
}

void upper_bound_test() {
tsci t;
std::string s1 = "aaa", s2 = "aab", s3 = "abc";
t.insert(s1);
t.insert(s2);
t.insert(s3);
BOOST_TEST(t.upper_bound(std::string("abb")) == t.find(std::string("abc")));
BOOST_TEST(t.upper_bound(std::string("b")) == t.end());
BOOST_TEST(t.upper_bound(s3) == t.end());
BOOST_TEST(t.upper_bound(s1) == t.find(s2));
t.insert(std::string("abcdef"));
BOOST_TEST(t.upper_bound(std::string("abcd")) == t.find(std::string("abcdef")));
t.insert(std::string("bbcccc"));
t.insert(std::string("bbd"));
BOOST_TEST(t.upper_bound(std::string("bbcccd")) == t.find(std::string("bbd")));
}

int main() {
insert_erase_test();
insert_find_test();
copy_test();
iterator_operator_plus();
iterator_operator_minus();
lower_bound_test();
upper_bound_test();
return boost::report_errors();
}

0 comments on commit 9ffbed8

Please sign in to comment.