mirror of
https://github.com/boostorg/unordered.git
synced 2025-07-31 20:04:29 +02:00
Only consider one node from each group in merge_unique
This commit is contained in:
@@ -3577,8 +3577,6 @@ struct table : boost::unordered::detail::functions<typename Types::hasher,
|
|||||||
return iterator(pos);
|
return iterator(pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Could speed this up a little by only considering
|
|
||||||
// the first node in a group.
|
|
||||||
template <typename Types2>
|
template <typename Types2>
|
||||||
void merge_unique(boost::unordered::detail::table<Types2>& other)
|
void merge_unique(boost::unordered::detail::table<Types2>& other)
|
||||||
{
|
{
|
||||||
@@ -3587,26 +3585,45 @@ struct table : boost::unordered::detail::functions<typename Types::hasher,
|
|||||||
(boost::is_same<node, typename other_table::node>::value));
|
(boost::is_same<node, typename other_table::node>::value));
|
||||||
BOOST_ASSERT(this->node_alloc() == other.node_alloc());
|
BOOST_ASSERT(this->node_alloc() == other.node_alloc());
|
||||||
|
|
||||||
if (other.size_) {
|
if (!other.size_) {
|
||||||
link_pointer prev = other.get_previous_start();
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
while (prev->next_) {
|
link_pointer prev = other.get_previous_start();
|
||||||
node_pointer n = other_table::next_node(prev);
|
node_pointer n = other_table::next_node(prev);
|
||||||
const_key_type& k = this->get_key(n);
|
while (n) {
|
||||||
std::size_t key_hash = this->hash(k);
|
const_key_type& k = this->get_key(n);
|
||||||
node_pointer pos = this->find_node(key_hash, k);
|
std::size_t key_hash = this->hash(k);
|
||||||
|
node_pointer pos = this->find_node(key_hash, k);
|
||||||
|
|
||||||
if (pos) {
|
if (pos) {
|
||||||
|
prev = n;
|
||||||
|
n = other_table::next_node(prev);
|
||||||
|
} else {
|
||||||
|
this->reserve_for_insert(this->size_ + 1);
|
||||||
|
|
||||||
|
prev->next_ = n->next_;
|
||||||
|
--other.size_;
|
||||||
|
other.fix_bucket(other.node_bucket(n), prev);
|
||||||
|
this->add_node_unique(n, key_hash);
|
||||||
|
n = other_table::next_node(prev);
|
||||||
|
|
||||||
|
// If the next node was from the same group, it's now
|
||||||
|
// the first node in the group.
|
||||||
|
if (n && !n->is_first_in_group()) {
|
||||||
|
n->set_first_in_group();
|
||||||
prev = n;
|
prev = n;
|
||||||
} else {
|
n = other_table::next_node(prev);
|
||||||
this->reserve_for_insert(this->size_ + 1);
|
}
|
||||||
prev->next_ = n->next_;
|
}
|
||||||
if (prev->next_ && n->is_first_in_group()) {
|
|
||||||
next_node(prev)->set_first_in_group();
|
// Skip over rest of group of nodes with equivalent keys,
|
||||||
}
|
// as we know there's already one in the container.
|
||||||
--other.size_;
|
while (n && !n->is_first_in_group()) {
|
||||||
other.fix_bucket(other.node_bucket(n), prev);
|
prev = n;
|
||||||
this->add_node_unique(n, key_hash);
|
n = other_table::next_node(prev);
|
||||||
|
if (!n) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user