29 #ifndef SPATIAL_RELAXED_KDTREE_HPP
30 #define SPATIAL_RELAXED_KDTREE_HPP
36 #include "spatial_ordered.hpp"
37 #include "spatial_mapping.hpp"
38 #include "spatial_equal.hpp"
39 #include "spatial_compress.hpp"
40 #include "spatial_value_compare.hpp"
41 #include "spatial_template_member_swap.hpp"
42 #include "spatial_assert.hpp"
43 #include "spatial_except.hpp"
68 template <
typename Rank>
73 {
return ((left + 1) < (right >> 1)); }
75 {
return ((right + 1) < (left >> 1)); }
96 template <
typename Rank>
101 if (weight < 2) weight = 2;
103 {
return ((right - left) > weight); }
105 {
return ((left - right) > weight); }
127 template <
typename Rank>
132 {
return ((right - left) > 2); }
134 {
return ((left - right) > 2); }
146 template <
typename Rank,
typename Key,
typename Value,
typename Compare,
147 typename Balancing,
typename Alloc>
181 typedef typename Alloc::template rebind
183 typedef typename Alloc::template rebind
204 const Balancing& balance,
const Link_allocator& alloc)
205 : Rank(rank),
_compare(balance, compare),
231 {
return static_cast<const_node_ptr
>(&
_impl.
_header()); }
261 {
return *
static_cast<Rank*
>(&
_impl); }
283 { link = alloc->allocate(1); }
295 link_ptr node = safe.release();
404 const_iterator
end()
const
422 const_reverse_iterator
rend()
const
425 const_reverse_iterator
crend()
const
441 {
return *
static_cast<const rank_type*
>(&
_impl); }
482 :
static_cast<const_link_ptr
>(
get_root())->weight;
523 find(
const key_type& key)
const
534 :
_impl(rank_type(), key_compare(), balancing_policy(),
535 Link_allocator()) { }
538 :
_impl(rank_, Compare(), Balancing(), Link_allocator())
542 :
_impl(rank_, compare_, Balancing(), Link_allocator())
546 const balancing_policy& balancing_)
547 :
_impl(rank_, compare_, balancing_, Link_allocator())
551 const balancing_policy& balancing_,
552 const allocator_type& allocator_)
553 :
_impl(rank_, compare_, balancing_, allocator_)
665 target_node->
parent = node;
671 SPATIAL_ASSERT_INVARIANT(*
this);
679 template<
typename InputIterator>
681 insert(InputIterator first, InputIterator last)
682 {
for (; first != last; ++first) {
insert(*first); } }
692 erase(iterator position);
701 erase(
const key_type& key);
707 template <
typename Rank,
typename Key,
typename Value,
typename Compare,
708 typename Balancing,
typename Alloc>
712 { left.
swap(right); }
726 template <
typename Rank,
typename Key,
typename Value,
typename Compare,
728 typename Balancing,
typename Alloc>
731 <Rank, Key, Value, Compare, Balancing, Alloc>& lhs,
733 <Rank, Key, Value, Compare, Balancing, Alloc>& rhs)
735 return lhs.size() == rhs.size()
740 template <
typename Rank,
typename Key,
typename Value,
typename Compare,
741 typename Balancing,
typename Alloc>
744 <Rank, Key, Value, Compare, Balancing, Alloc>& lhs,
746 <Rank, Key, Value, Compare, Balancing, Alloc>& rhs)
747 {
return !(lhs == rhs); }
762 template <
typename Rank,
typename Key,
typename Value,
typename Compare,
764 typename Balancing,
typename Alloc>
767 <Rank, Key, Value, Compare, Balancing, Alloc>& lhs,
769 <Rank, Key, Value, Compare, Balancing, Alloc>& rhs)
771 return std::lexicographical_compare
776 template <
typename Rank,
typename Key,
typename Value,
typename Compare,
777 typename Balancing,
typename Alloc>
780 <Rank, Key, Value, Compare, Balancing, Alloc>& lhs,
782 <Rank, Key, Value, Compare, Balancing, Alloc>& rhs)
783 {
return rhs < lhs; }
785 template <
typename Rank,
typename Key,
typename Value,
typename Compare,
786 typename Balancing,
typename Alloc>
789 <Rank, Key, Value, Compare, Balancing, Alloc>& lhs,
791 <Rank, Key, Value, Compare, Balancing, Alloc>& rhs)
792 {
return !(rhs < lhs); }
794 template <
typename Rank,
typename Key,
typename Value,
typename Compare,
795 typename Balancing,
typename Alloc>
798 <Rank, Key, Value, Compare, Balancing, Alloc>& lhs,
800 <Rank, Key, Value, Compare, Balancing, Alloc>& rhs)
801 {
return !(lhs < rhs); }
804 template <
typename Rank,
typename Key,
typename Value,
typename Compare,
805 typename Balancing,
typename Alloc>
807 Relaxed_kdtree<Rank, Key, Value, Compare, Balancing, Alloc>
808 ::destroy_all_nodes()
813 if (node->
left != 0) { node = node->
left; }
814 else if (node->
right != 0) { node = node->
right; }
820 set_root(get_header());
821 set_leftmost(get_header());
822 set_rightmost(get_header());
826 if (p->
left == node) { p->
left = 0; }
827 else { p->
right = 0; }
829 SPATIAL_ASSERT_CHECK(node != 0);
830 SPATIAL_ASSERT_CHECK(p != 0);
837 template <
typename Rank,
typename Key,
typename Value,
typename Compare,
838 typename Balancing,
typename Alloc>
844 SPATIAL_ASSERT_CHECK(!other.
empty());
845 SPATIAL_ASSERT_CHECK(empty());
847 node_ptr node = clone_node(other_node);
848 node->
parent = get_header();
852 while(!
header(other_node))
854 if (other_node->
left != 0)
856 other_node = other_node->
left;
857 node_ptr target = clone_node(other_node);
862 else if (other_node->
right != 0)
864 other_node = other_node->
right;
865 node_ptr target = clone_node(other_node);
867 node->
right = target;
884 other_node = other_node->
right;
885 node_ptr target = clone_node(other_node);
887 node->
right = target;
892 SPATIAL_ASSERT_CHECK(!empty());
893 SPATIAL_ASSERT_CHECK(
header(other_node));
894 SPATIAL_ASSERT_CHECK(
header(node));
898 set_leftmost(
minimum(get_root()));
899 set_rightmost(
maximum(get_root()));
902 template <
typename Rank,
typename Key,
typename Value,
typename Compare,
903 typename Balancing,
typename Alloc>
911 bool left_node = (p->
left == node);
913 erase_node(node_dim, node);
917 insert_node(node_dim, replacing, node);
921 template <
typename Rank,
typename Key,
typename Value,
typename Compare,
922 typename Balancing,
typename Alloc>
929 SPATIAL_ASSERT_CHECK(node != 0);
930 SPATIAL_ASSERT_CHECK(!
header(node));
939 || (!key_comp()(node_dim,
948 node->
left = target_node;
949 target_node->
parent = node;
950 if (get_leftmost() == node)
951 { set_leftmost(target_node); }
952 ++
link(node)->weight;
962 node = balance_node(node_dim, node);
966 ++
link(node)->weight;
968 node_dim =
incr_dim(rank(), node_dim);
974 if (node->
right == 0)
976 node->
right = target_node;
977 target_node->
parent = node;
978 if (get_rightmost() == node)
979 { set_rightmost(target_node); }
980 ++
link(node)->weight;
990 node = balance_node(node_dim, node);
994 ++
link(node)->weight;
996 node_dim =
incr_dim(rank(), node_dim);
1001 SPATIAL_ASSERT_CHECK(target_node != 0);
1002 SPATIAL_ASSERT_CHECK(!
header(target_node));
1004 SPATIAL_ASSERT_CHECK(target_node->
right == 0);
1005 SPATIAL_ASSERT_CHECK(target_node->
left == 0);
1006 SPATIAL_ASSERT_CHECK(target_node->
parent != 0);
1010 template <
typename Rank,
typename Key,
typename Value,
typename Compare,
1011 typename Balancing,
typename Alloc>
1019 SPATIAL_ASSERT_CHECK(node != 0);
1020 SPATIAL_ASSERT_CHECK(!
header(node));
1022 SPATIAL_ASSERT_CHECK(get_rightmost() != get_leftmost());
1024 while (node->
right != 0 || node->
left != 0)
1026 std::pair<node_ptr, dimension_type> candidate;
1028 && (node->
right == 0
1034 rank(), node_dim, key_comp());
1035 if (get_leftmost() == candidate.first)
1036 { set_leftmost(node); }
1037 if (get_rightmost() == node)
1038 { set_rightmost(candidate.first); }
1045 rank(), node_dim, key_comp());
1046 if (get_rightmost() == candidate.first)
1047 { set_rightmost(node); }
1048 if (get_leftmost() == node)
1049 { set_leftmost(candidate.first); }
1052 node = candidate.first;
1053 node_dim = candidate.second;
1055 SPATIAL_ASSERT_CHECK(!
header(node));
1056 SPATIAL_ASSERT_CHECK(node != 0);
1057 SPATIAL_ASSERT_CHECK(node->
right == 0);
1058 SPATIAL_ASSERT_CHECK(node->
left == 0);
1059 SPATIAL_ASSERT_CHECK(node->
parent != 0);
1061 if (p->
left == node)
1064 if (get_leftmost() == node) { set_leftmost(p); }
1069 if (get_rightmost() == node) { set_rightmost(p); }
1072 while(node->
parent != parent)
1075 node_dim =
decr_dim(rank(), node_dim);
1076 SPATIAL_ASSERT_CHECK(
const_link(node)->weight > 1);
1077 --
link(node)->weight;
1083 node = balance_node(node_dim, node);
1086 SPATIAL_ASSERT_CHECK(!
header(node));
1087 SPATIAL_ASSERT_CHECK(node != 0);
1091 template <
typename Rank,
typename Key,
typename Value,
typename Compare,
1092 typename Balancing,
typename Alloc>
1098 SPATIAL_ASSERT_CHECK(!
header(node));
1099 SPATIAL_ASSERT_CHECK(node != 0);
1100 if (node == get_root()
1104 set_root(get_header());
1105 set_leftmost(get_header());
1106 set_rightmost(get_header());
1111 erase_node(node_dim, node);
1112 node_dim =
decr_dim(rank(), node_dim);
1115 SPATIAL_ASSERT_CHECK(
const_link(p)->weight > 1);
1121 { p = balance_node(node_dim, p); }
1123 node_dim =
decr_dim(rank(), node_dim);
1128 template <
typename Rank,
typename Key,
typename Value,
typename Compare,
1129 typename Balancing,
typename Alloc>
1144 erase_node_balance(node_dim, target.
node);
1145 destroy_node(target.
node);
1146 SPATIAL_ASSERT_INVARIANT(*
this);
1149 template <
typename Rank,
typename Key,
typename Value,
typename Compare,
1150 typename Balancing,
typename Alloc>
1165 first_equal(get_root(), 0, rank(), key_comp(), key));
1166 if (node == get_header())
break;
1167 erase_node_balance(dim, node);
1171 SPATIAL_ASSERT_INVARIANT(*
this);
1178 #endif // SPATIAL_RELAXED_KDTREE_HPP
size_type size() const
Returns the number of elements in the K-d tree.
Relaxed_kdtree & operator=(const Relaxed_kdtree &other)
Assignment of other into the tree, with deep copy.
bool operator<(const Kdtree< Rank, Key, Value, Compare, Alloc > &lhs, const Kdtree< Rank, Key, Value, Compare, Alloc > &rhs)
Operations <, >, <= and >= behave as if using algorithm lexicographical_compare, which compares the e...
std::pair< NodePtr, dimension_type > first_equal(NodePtr node, dimension_type dim, Rank rank, KeyCompare key_comp, const Key &key)
mutate< Value >::type value_type
A bidirectional iterator traversing all node in the tree in inorder traversal.
A bidirectional iterator traversing all node in the tree in inorder traversal.
key_compare & get_compare()
Detailed implementation of the kd-tree.
const_node_ptr get_leftmost() const
Relaxed_kdtree< Rank, Key, Value, Compare, Balancing, Alloc > Self
const Value * const_pointer
std::pair< NodePtr, dimension_type > minimum_mapping(NodePtr node, dimension_type dim, Rank rank, dimension_type map, KeyCompare key_comp)
Move the iterator given in parameter to the minimum value along the iterator's mapping dimension but ...
node_ptr node
The node pointed to by the iterator.
node_ptr clone_node(const_node_ptr node)
node_ptr balance_node(dimension_type dim, node_ptr node)
Attempt to balance the current node.
void set_rightmost(node_ptr x)
const_reverse_iterator rend() const
Relaxed_kdtree(const rank_type &rank_, const key_compare &compare_, const balancing_policy &balancing_)
Link_allocator & get_link_allocator()
mode_type::const_link_ptr const_link_ptr
~Relaxed_kdtree()
Deallocate all nodes in the destructor.
mode_type::const_node_ptr const_node_ptr
void copy_structure(const Self &other)
Copy the exact sturcture of the sub-tree pointed to by other_node into the current empty tree...
std::ptrdiff_t difference_type
bool operator==(const Kdtree< Rank, Key, Value, Compare, Alloc > &lhs, const Kdtree< Rank, Key, Value, Compare, Alloc > &rhs)
The == and != operations is performed by first comparing sizes, and if they match, the elements are compared sequentially using algorithm std::equal, which stops at the first mismatch.
std::reverse_iterator< const_iterator > const_reverse_iterator
Relaxed_kdtree(const rank_type &rank_)
iterator insert_node(dimension_type node_dim, node_ptr node, node_ptr new_node)
Insert the new node new_node into the tree located at node.
This policy triggers rebalancing for the node when the difference in weight between left or right is ...
const_reverse_iterator crbegin() const
const_iterator cbegin() const
Compress< Link_allocator, Node< mode_type > > _header
The basic node for any tree in the library.
Implementation(const Implementation &impl)
node_ptr erase_node(dimension_type dim, node_ptr node)
Erase the node pointed by node.
bool operator()(const Rank &, weight_type left, weight_type right) const
Rebalancing predicate.
bool operator()(const Rank &, weight_type left, weight_type right) const
Rebalancing predicate.
bool operator<=(const Kdtree< Rank, Key, Value, Compare, Alloc > &lhs, const Kdtree< Rank, Key, Value, Compare, Alloc > &rhs)
Operations <, >, <= and >= behave as if using algorithm lexicographical_compare, which compares the e...
size_type count() const
Returns the number of elements in the K-d tree.
ordered_iterator< Container > ordered_begin(Container &container)
Finds the value in container for which its key has the smallest coordinate over the dimension ordered...
void destroy_node(node_ptr node)
Destroy and deallocate node.
bool operator>=(const Kdtree< Rank, Key, Value, Compare, Alloc > &lhs, const Kdtree< Rank, Key, Value, Compare, Alloc > &rhs)
Operations <, >, <= and >= behave as if using algorithm lexicographical_compare, which compares the e...
Node< Link > * maximum(Node< Link > *x)
Reach the left most node.
const_reverse_iterator rbegin() const
void swap(Self &other)
Swap the K-d tree content with others.
bool operator()(const Rank &rank, weight_type left, weight_type right) const
Rebalancing predicate.
void clear()
Erase all elements in the K-d tree.
Relaxed_kdtree(const rank_type &rank_, const key_compare &compare_, const balancing_policy &balancing_, const allocator_type &allocator_)
Node * left
A pointer to the left child node of the current node.
const Kdtree_link< Key, Value >::value_type & const_value(const Node< Kdtree_link< Key, Value > > *node)
This function converts a pointer on a node into a value for a Kdtree_link type.
const Kdtree_link< Value, Value >::key_type & const_key(const Node< Kdtree_link< Value, Value > > *node)
This function converts a pointer on a node into a key for a Kdtree_link type.
safe_allocator(Link_allocator &a)
key_compare key_comp() const
Returns the compare function used for the key.
Relaxed_kdtree(const rank_type &rank_, const key_compare &compare_)
bool header(const Node< Link > *x)
Check if node is a header node.
Tp * mutate_pointer(const Tp *p)
A helper functions that mutates pointers.
ValueCompare< value_type, key_compare > value_compare
Node< Link > * minimum(Node< Link > *x)
Reach the left most node.
bool operator!=(const Kdtree< Rank, Key, Value, Compare, Alloc > &lhs, const Kdtree< Rank, Key, Value, Compare, Alloc > &rhs)
The == and != operations is performed by first comparing sizes, and if they match, the elements are compared sequentially using algorithm std::equal, which stops at the first mismatch.
void erase(iterator position)
Deletes the node pointed to by the iterator.
Alloc::template rebind< Relaxed_kdtree_link< Key, Value > >::other Link_allocator
void erase_node_balance(dimension_type dim, node_ptr node)
Erase the node pointed by node and balance tree up to header.
const_iterator find(const key_type &key) const
Find the first node that matches with key and returns an iterator to it found, otherwise it returns a...
iterator insert(const value_type &value)
Insert a single key key in the tree.
bool empty() const
True if the tree is empty.
const_iterator end() const
Value compare functor for container storing pairs of (Key, Mapped) types, such as in spatial::point_m...
balancing_policy balancing() const
Returns the balancing policy for the container.
std::size_t size_type
Defines a positive integral type for counting objects or storing absolute values. ...
node_ptr node
The node pointed to by the iterator.
bool operator>(const Kdtree< Rank, Key, Value, Compare, Alloc > &lhs, const Kdtree< Rank, Key, Value, Compare, Alloc > &rhs)
Operations <, >, <= and >= behave as if using algorithm lexicographical_compare, which compares the e...
void insert(InputIterator first, InputIterator last)
Insert a serie of values in the tree at once.
void check_iterator(Ptr1 ptr1, Ptr2 ptr2)
Checks if two iterators are of equal values, if not raises the invalid_iterator exception.
Relaxed_kdtree(const Relaxed_kdtree &other)
Deep copy of other into the new tree.
ordered_iterator< Container > ordered_end(Container &container)
Finds the past-the-end position in container for this constant iterator.
value_compare value_comp() const
Returns the compare function used for the value.
std::size_t weight_type
Defines weight as being a size.
spatial::details::Relaxed_kdtree::Implementation _impl
mode_type::link_ptr link_ptr
std::size_t dimension_type
Defines the type for the dimension as being a size.
weight_type weight
The weight is equal to 1 plus the amount of child nodes below the current node.
Implementation(const rank_type &rank, const key_compare &compare, const Balancing &balance, const Link_allocator &alloc)
Const_node_iterator< mode_type > const_iterator
const Kdtree_link< Key, Value > * const_link(const Node< Kdtree_link< Key, Value > > *node)
This function converts a pointer on a node into a link for a Kdtree_link type.
Define a weighted link type for the relaxed k-d tree.
const_node_ptr get_root() const
A policy that balances a node if the difference in weight between left and right is higher than 2 (tw...
void set_root(node_ptr x)
const Value & const_reference
const_node_ptr get_header() const
void assign(Type1 &first, Type2 &second, const std::pair< Type1, Type2 > &pair)
balancing_policy & get_balancing()
Balancing balancing_policy
Compress< Balancing, key_compare > _compare
static void do_it(Tp &left, Tp &right)
std::pair< NodePtr, dimension_type > maximum_mapping(NodePtr node, dimension_type dim, Rank rank, dimension_type map, KeyCompare key_comp)
Move the iterator given in parameter to the maximum value along the iterator's mapping dimension but ...
The main namespace used in the library.
Relaxed_kdtree_link< Key, Value > mode_type
void destroy_all_nodes()
Destroy and deallocate all nodes in the container.
mutate< Key >::type key_type
dimension_type decr_dim(Rank rank, dimension_type node_dim)
Decrement dimension node_dim, given rank.
const Base & base() const
Accessor to the base class.
void swap_node(Node< Kdtree_link< Key, Value > > *&a, Node< Kdtree_link< Key, Value > > *&b)
Swaps nodes position in the tree.
const_iterator cend() const
A policy that balances a node if the difference in weight between left and right is higher than the c...
Value_allocator get_value_allocator() const
Node * right
A pointer to the right child node of the current node.
const_reverse_iterator crend() const
const_iterator begin() const
std::reverse_iterator< iterator > reverse_iterator
Kdtree_link< Key, Value > * link(Node< Kdtree_link< Key, Value > > *node)
This function converts a pointer on a node into a link for a Kdtree_link type.
dimension_type dimension() const
Returns the dimension of the container.
void set_leftmost(node_ptr x)
node_ptr create_node(const value_type &value)
reverse_iterator rbegin()
const_node_ptr get_rightmost() const
Alloc::template rebind< value_type >::other Value_allocator
Kdtree_link< Key, Value >::value_type & value(Node< Kdtree_link< Key, Value > > *node)
This function converts a pointer on a node into a value for a Kdtree_link type.
void check_node_iterator(Node *node)
Checks that the node pointed to by an iterator and given as an argument to a function is not null or ...
Node * parent
A pointer to the parent of the current node.
rank_type rank() const
Returns the rank type used internally to get the number of dimensions in the container.
void swap(Kdtree< Rank, Key, Value, Compare, Alloc > &left, Kdtree< Rank, Key, Value, Compare, Alloc > &right)
Swap the content of the tree left and right.
iterator find(const key_type &key)
Find the first node that matches with key and returns an iterator to it found, otherwise it returns a...
mode_type::node_ptr node_ptr
allocator_type get_allocator() const
Returns the allocator used by the tree.
dimension_type incr_dim(Rank rank, dimension_type node_dim)
Increment dimension node_dim, given rank.
size_type max_size() const
The maximum number of elements that can be allocated.
Node_iterator< mode_type > iterator