20 #ifndef SPATIAL_KDTREE_HPP
21 #define SPATIAL_KDTREE_HPP
26 #include "spatial_ordered.hpp"
27 #include "spatial_mapping.hpp"
28 #include "spatial_equal.hpp"
29 #include "spatial_compress.hpp"
30 #include "spatial_value_compare.hpp"
31 #include "spatial_template_member_swap.hpp"
32 #include "spatial_assert.hpp"
33 #include "spatial_except.hpp"
48 template <
typename Rank,
typename Key,
typename Value,
typename Compare,
81 typedef typename Alloc::template rebind
83 typedef typename Alloc::template rebind
104 const Link_allocator& alloc)
128 : key_compare(key_comp),
node(node_) { }
130 {
return static_cast<key_compare
>(*this); }
140 {
return static_cast<const_node_ptr
>(&
_impl.
_header()); }
170 {
return *
static_cast<Rank*
>(&
_impl); }
189 { link = alloc->allocate(1); }
201 link_ptr node = safe.release();
238 (
typename std::vector<node_ptr>::iterator first,
239 typename std::vector<node_ptr>::iterator last,
dimension_type dim,
247 typename std::vector<node_ptr>::iterator
249 (
typename std::vector<node_ptr>::iterator first,
250 typename std::vector<node_ptr>::iterator last,
dimension_type dim);
288 const_iterator
end()
const
305 const_reverse_iterator
rend()
const
308 const_reverse_iterator
crend()
const
316 {
return *
static_cast<const Rank*
>(&
_impl); }
372 :
_impl(rank_type(), key_compare(), allocator_type())
376 :
_impl(rank_, key_compare(), allocator_type())
379 explicit Kdtree(
const key_compare& compare_)
380 :
_impl(rank_type(), compare_, allocator_type())
383 Kdtree(
const rank_type& rank_,
const key_compare& compare_)
384 :
_impl(rank_, compare_, allocator_type())
387 Kdtree(
const rank_type& rank_,
const key_compare& compare_,
388 const allocator_type& allocator_)
389 :
_impl(rank_, compare_, allocator_)
514 template<
typename InputIterator>
516 insert(InputIterator first, InputIterator last)
517 {
for (; first != last; ++first) {
insert(*first); } }
527 template<
typename InputIterator>
559 find(
const key_type& key)
const
576 erase(iterator pointer);
592 template <
typename Rank,
typename Key,
typename Value,
typename Compare,
597 { left.
swap(right); }
611 template <
typename Rank,
typename Key,
typename Value,
typename Compare,
623 template <
typename Rank,
typename Key,
typename Value,
typename Compare,
628 {
return !(lhs == rhs); }
643 template <
typename Rank,
typename Key,
typename Value,
typename Compare,
647 operator<(const Kdtree<Rank, Key, Value, Compare, Alloc>& lhs,
650 return std::lexicographical_compare
655 template <
typename Rank,
typename Key,
typename Value,
typename Compare,
660 {
return rhs < lhs; }
662 template <
typename Rank,
typename Key,
typename Value,
typename Compare,
665 operator<=(const Kdtree<Rank, Key, Value, Compare, Alloc>& lhs,
667 {
return !(rhs < lhs); }
669 template <
typename Rank,
typename Key,
typename Value,
typename Compare,
674 {
return !(lhs < rhs); }
677 template <
typename Rank,
typename Key,
typename Value,
typename Compare,
680 Kdtree<Rank, Key, Value, Compare, Alloc>
681 ::destroy_all_nodes()
686 if (node->
left != 0) { node = node->
left; }
687 else if (node->
right != 0) { node = node->
right; }
693 set_root(get_header());
694 set_leftmost(get_header());
695 set_rightmost(get_header());
699 if (p->
left == node) { p->
left = 0; }
700 else { p->
right = 0; }
702 SPATIAL_ASSERT_CHECK(node != 0);
703 SPATIAL_ASSERT_CHECK(p != 0);
710 template <
typename Rank,
typename Key,
typename Value,
typename Compare,
717 SPATIAL_ASSERT_CHECK(target_node != 0);
718 SPATIAL_ASSERT_CHECK(target_node->
right == 0);
719 SPATIAL_ASSERT_CHECK(target_node->
left == 0);
724 SPATIAL_ASSERT_CHECK(_impl._count() == 0);
725 target_node->
parent = get_header();
726 set_root(target_node);
727 set_leftmost(target_node);
728 set_rightmost(target_node);
735 if (key_comp()(node_dim,
741 node_dim =
incr_dim(rank(), node_dim);
745 node->
left = target_node;
746 target_node->
parent = node;
747 if (node == get_leftmost()) { set_leftmost(target_node); }
754 if (node->
right != 0)
757 node_dim =
incr_dim(rank(), node_dim);
761 node->
right = target_node;
762 target_node->
parent = node;
763 if (node == get_rightmost())
764 { set_rightmost(target_node); }
771 SPATIAL_ASSERT_CHECK(empty() ==
false);
772 SPATIAL_ASSERT_CHECK(_impl._count() != 0);
773 SPATIAL_ASSERT_CHECK(target_node->
right == 0);
774 SPATIAL_ASSERT_CHECK(target_node->
left == 0);
775 SPATIAL_ASSERT_CHECK(target_node->
parent != 0);
776 SPATIAL_ASSERT_INVARIANT(*
this);
780 template <
typename Rank,
typename Key,
typename Value,
typename Compare,
786 SPATIAL_ASSERT_CHECK(!other.
empty());
787 SPATIAL_ASSERT_CHECK(empty());
790 node->
parent = get_header();
794 while(!
header(other_node))
796 if (other_node->
left != 0)
798 other_node = other_node->
left;
805 else if (other_node->
right != 0)
807 other_node = other_node->
right;
811 node->
right = target;
827 other_node = other_node->
right;
831 node->
right = target;
836 SPATIAL_ASSERT_CHECK(!empty());
837 SPATIAL_ASSERT_CHECK(
header(other_node));
838 SPATIAL_ASSERT_CHECK(
header(node));
842 set_leftmost(
minimum(get_root()));
843 set_rightmost(
maximum(get_root()));
844 _impl._count() = other.
size();
845 SPATIAL_ASSERT_CHECK(size() != 0);
846 SPATIAL_ASSERT_CHECK(size() == other.
size());
847 SPATIAL_ASSERT_INVARIANT(*
this);
850 template <
typename Rank,
typename Key,
typename Value,
typename Compare,
856 SPATIAL_ASSERT_CHECK(empty());
857 SPATIAL_ASSERT_CHECK(!other.
empty());
858 std::vector<node_ptr> ptr_store;
859 ptr_store.reserve(other.
size());
863 { ptr_store.push_back(create_node(*i)); }
867 for(
typename std::vector<node_ptr>::iterator i = ptr_store.begin();
868 i != ptr_store.end(); ++i)
869 { destroy_node(*i); }
872 set_root(rebalance_node_insert(ptr_store.begin(), ptr_store.end(), 0,
875 while (root->
left != 0) root = root->
left;
880 _impl._count() = other.
size();
881 SPATIAL_ASSERT_CHECK(!empty());
882 SPATIAL_ASSERT_CHECK(size() != 0);
883 SPATIAL_ASSERT_INVARIANT(*
this);
886 template <
typename InputIterator>
887 inline std::ptrdiff_t
889 (InputIterator first, InputIterator last, std::random_access_iterator_tag)
890 {
return last - first; }
892 template <
typename InputIterator>
893 inline std::ptrdiff_t
895 (InputIterator, InputIterator, std::input_iterator_tag)
898 template <
typename Rank,
typename Key,
typename Value,
typename Compare,
900 template <
typename InputIterator>
902 Kdtree<Rank, Key, Value, Compare, Alloc>
903 ::insert_rebalance(InputIterator first, InputIterator last)
905 if (first == last && empty())
return;
906 std::vector<node_ptr> ptr_store;
911 typename std::iterator_traits<InputIterator>::iterator_category()));
914 for(InputIterator i = first; i != last; ++i)
915 { ptr_store.push_back(create_node(*i)); }
919 for(
typename std::vector<node_ptr>::iterator i = ptr_store.begin();
920 i != ptr_store.end(); ++i)
921 { destroy_node(*i); }
924 for(
iterator i = begin(); i != end(); ++i)
925 { ptr_store.push_back(i.node); }
926 set_root(rebalance_node_insert(ptr_store.begin(), ptr_store.end(), 0,
929 while (root->
left != 0) root = root->
left;
934 _impl._count() = ptr_store.size();
935 SPATIAL_ASSERT_CHECK(!empty());
936 SPATIAL_ASSERT_CHECK(size() != 0);
937 SPATIAL_ASSERT_INVARIANT(*
this);
940 template <
typename Rank,
typename Key,
typename Value,
typename Compare,
946 std::vector<node_ptr> ptr_store;
947 ptr_store.reserve(size());
948 for(
iterator i = begin(); i != end(); ++i)
949 { ptr_store.push_back(i.node); }
950 set_root(rebalance_node_insert(ptr_store.begin(), ptr_store.end(), 0,
953 while (node->
left != 0) node = node->
left;
958 SPATIAL_ASSERT_CHECK(!empty());
959 SPATIAL_ASSERT_CHECK(size() != 0);
960 SPATIAL_ASSERT_INVARIANT(*
this);
963 template<
typename Compare,
typename Node_ptr>
970 : compare(c), dimension(d) { }
979 template <
typename Rank,
typename Key,
typename Value,
typename Compare,
982 std::vector<typename Kdtree<Rank, Key, Value, Compare, Alloc>::node_ptr>
985 (
typename std::vector<node_ptr>::iterator first,
986 typename std::vector<node_ptr>::iterator last,
989 SPATIAL_ASSERT_CHECK(first != last);
992 if (first == (last - 1))
return first;
993 typename std::vector<node_ptr>::iterator mid = first + (last - first) / 2;
994 std::nth_element(first, mid, last, less);
995 typename std::vector<node_ptr>::iterator seek = mid;
996 typename std::vector<node_ptr>::iterator pivot = mid;
1000 SPATIAL_ASSERT_CHECK(!less(*mid, *seek));
1001 if (!less(*seek, *mid))
1004 if (seek != pivot) { std::swap(*seek, *pivot); }
1006 SPATIAL_ASSERT_CHECK(!less(*pivot, *mid) && !less(*mid, *pivot));
1009 while (seek != first);
1010 SPATIAL_ASSERT_CHECK(pivot != last);
1014 template <
typename Rank,
typename Key,
typename Value,
typename Compare,
1019 (
typename std::vector<node_ptr>::iterator first,
1020 typename std::vector<node_ptr>::iterator last,
1023 SPATIAL_ASSERT_CHECK(first != last);
1024 SPATIAL_ASSERT_CHECK(dim < dimension());
1025 typename std::vector<node_ptr>::iterator med
1026 = median(first, last, dim);
1030 if (med + 1 != last)
1031 { root->
right = rebalance_node_insert(med + 1, last, dim, root); }
1032 else root->
right = 0;
1035 while(first != last)
1037 med = median(first, last, dim);
1039 parent->
left = node;
1042 if (med + 1 != last)
1043 { node->
right = rebalance_node_insert(med + 1, last, dim, node); }
1044 else node->
right = 0;
1049 SPATIAL_ASSERT_CHECK(parent->
left == 0);
1050 SPATIAL_ASSERT_CHECK(root->
parent != root);
1054 template <
typename Rank,
typename Key,
typename Value,
typename Compare,
1060 SPATIAL_ASSERT_CHECK(node != 0);
1061 SPATIAL_ASSERT_CHECK(!
header(node));
1063 while (node->
right != 0 || node->
left != 0)
1073 if (node->
right == 0)
1077 if (get_rightmost() == node)
1080 if (get_leftmost() == seeker) { set_leftmost(node); }
1083 while (seeker->
left != 0)
1085 seeker = seeker->
left;
1086 if (get_leftmost() == seeker)
1087 { set_leftmost(node);
break; }
1091 std::pair<node_ptr, dimension_type> candidate
1093 rank(), node_dim, key_comp());
1094 if (get_rightmost() == candidate.first)
1095 { set_rightmost(node); }
1096 if (get_leftmost() == node)
1097 { set_leftmost(candidate.first); }
1098 if (first_swap == 0)
1099 { first_swap = candidate.first; }
1101 node = candidate.first;
1102 node_dim = candidate.second;
1104 SPATIAL_ASSERT_CHECK(node != 0);
1105 SPATIAL_ASSERT_CHECK(node->
right == 0);
1106 SPATIAL_ASSERT_CHECK(node->
left == 0);
1107 SPATIAL_ASSERT_CHECK(node->
parent != 0);
1111 SPATIAL_ASSERT_CHECK(count() == 1);
1112 set_root(get_header());
1113 set_leftmost(get_header());
1114 set_rightmost(get_header());
1116 else if (p->
left == node)
1119 if (get_leftmost() == node) { set_leftmost(p); }
1124 if (get_rightmost() == node) { set_rightmost(p); }
1127 SPATIAL_ASSERT_CHECK((get_header() == get_root())
1128 ? (_impl._count() == 0) :
true);
1130 SPATIAL_ASSERT_INVARIANT(*
this);
1134 template <
typename Rank,
typename Key,
typename Value,
typename Compare,
1149 erase_node(node_dim, target.
node);
1152 template <
typename Rank,
typename Key,
typename Value,
typename Compare,
1159 if (empty())
return 0;
1165 if (
header(node))
return 0;
1169 node_ptr tmp = erase_node(dim, node);
1171 if (tmp == 0)
break;
1174 if (tmp->
parent == node)
break;
1182 #endif // SPATIAL_KDTREE_HPP
mutate< Key >::type key_type
~Kdtree()
Deallocate all nodes in the destructor.
Compress< Link_allocator, Node< mode_type > > _header
void rebalance()
Rebalance the k-d tree near-optimally, resulting in order of complexity on most search functions...
Const_node_iterator< mode_type > const_iterator
const_reverse_iterator rend() const
A bidirectional iterator traversing all node in the tree in inorder traversal.
A bidirectional iterator traversing all node in the tree in inorder traversal.
Implementation(const Implementation &impl)
Alloc::template rebind< Kdtree_link< Key, Value > >::other Link_allocator
Kdtree(const key_compare &compare_)
iterator insert_node(node_ptr target_node)
Insert a node already allocated into the tree.
mutate< Value >::type value_type
const_iterator cbegin() const
mode_type::node_ptr node_ptr
key_compare key_comp() const
Returns the compare function used for the key.
void copy_structure(const Self &other)
Copy the exact sturcture of the sub-tree pointed to by other_node into the current empty tree...
node_ptr create_node(const value_type &value)
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.
bool empty() const
True if the tree is empty.
node_ptr erase_node(dimension_type node_dim, node_ptr node)
Erase the node located at node with current dimension node_dim.
const_reverse_iterator crend() const
iterator insert(const value_type &value)
Insert a single value element in the container.
size_type max_size() const
The maximum number of elements that can be allocated.
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.
dimension_type dimension() const
Returns the dimension of the tree.
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...
std::reverse_iterator< const_iterator > const_reverse_iterator
void swap(Self &other)
Swap the K-d tree content with others.
The basic node for any tree in the library.
const_node_ptr get_rightmost() const
mode_type::const_node_ptr const_node_ptr
Node< mode_type > * _leftmost
bool operator()(const Node_ptr &x, const Node_ptr &y) const
const_iterator end() const
ordered_iterator< Container > ordered_begin(Container &container)
Finds the value in container for which its key has the smallest coordinate over the dimension ordered...
const_iterator begin() const
Kdtree(const rank_type &rank_, const key_compare &compare_, const allocator_type &allocator_)
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...
const Value * const_pointer
Node< Link > * maximum(Node< Link > *x)
Reach the left most node.
Implementation(const rank_type &rank, const key_compare &compare, const Link_allocator &alloc)
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.
void erase(iterator pointer)
Deletes the node pointed to by the iterator.
safe_allocator(Link_allocator &a)
std::vector< node_ptr >::iterator median(typename std::vector< node_ptr >::iterator first, typename std::vector< node_ptr >::iterator last, dimension_type dim)
This function finds the median node in a random iterator range.
bool header(const Node< Link > *x)
Check if node is a header node.
mode_type::const_link_ptr const_link_ptr
Tp * mutate_pointer(const Tp *p)
A helper functions that mutates pointers.
std::reverse_iterator< iterator > reverse_iterator
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.
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...
Value compare functor for container storing pairs of (Key, Mapped) types, such as in spatial::point_m...
size_type size() const
Returns the number of elements in the K-d tree.
rank_type rank() const
Returns the rank used to create the tree.
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...
value_compare value_comp() const
Returns the compare function used for the value.
void check_iterator(Ptr1 ptr1, Ptr2 ptr2)
Checks if two iterators are of equal values, if not raises the invalid_iterator exception.
const_reverse_iterator rbegin() const
key_compare & get_compare()
ordered_iterator< Container > ordered_end(Container &container)
Finds the past-the-end position in container for this constant iterator.
const_node_ptr get_root() const
const_node_ptr get_header() const
std::size_t dimension_type
Defines the type for the dimension as being a size.
Maximum(const key_compare &key_comp, node_ptr node_)
allocator_type get_allocator() const
Returns the allocator used by the tree.
void destroy_all_nodes()
Destroy and deallocate all nodes in the container.
mapping_compare(const Compare &c, dimension_type d)
ValueCompare< value_type, key_compare > value_compare
Link_allocator & get_link_allocator()
std::ptrdiff_t difference_type
void assign(Type1 &first, Type2 &second, const std::pair< Type1, Type2 > &pair)
spatial::details::Kdtree::Implementation _impl
const_node_ptr get_leftmost() const
reverse_iterator rbegin()
void insert(InputIterator first, InputIterator last)
Insert a serie of values in the container at once.
static void do_it(Tp &left, Tp &right)
Define the link type for a Kdtree that contains the value member.
The main namespace used in the library.
void set_leftmost(node_ptr x)
void set_rightmost(node_ptr x)
void clear()
Erase all elements in the K-d tree.
const Base & base() const
Accessor to the base class.
node_ptr rebalance_node_insert(typename std::vector< node_ptr >::iterator first, typename std::vector< node_ptr >::iterator last, dimension_type dim, node_ptr header)
Insert all the nodes in [first,last) into the tree, by first sorting the nodes according to the dimen...
const_iterator cend() const
void swap_node(Node< Kdtree_link< Key, Value > > *&a, Node< Kdtree_link< Key, Value > > *&b)
Swaps nodes position in the tree.
Detailed implementation of the kd-tree.
size_type count() const
Returns the number of elements in the K-d tree.
Node * right
A pointer to the right child node of the current node.
Self & operator=(const Self &other)
Assignment of other into the tree, with deep copy.
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.
const Value & const_reference
Value_allocator get_value_allocator() const
void copy_rebalance(const Self &other)
Copy the content of other to the tree and rebalances the values in the tree resulting in most query h...
mode_type::link_ptr link_ptr
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.
std::pair< NodePtr, dimension_type > preorder_first(NodePtr node, dimension_type dim, Rank rank, const Query &query)
Kdtree_link< Key, Value > mode_type
Kdtree(const Self &other, bool balancing=false)
Deep copy of other into the new tree.
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 ...
Alloc::template rebind< value_type >::other Value_allocator
Node * parent
A pointer to the parent of the current node.
Compress< key_compare, size_type > _count
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.
Kdtree(const rank_type &rank_)
const_reverse_iterator crbegin() const
Node_iterator< mode_type > iterator
void destroy_node(node_ptr node)
Destroy and deallocate node.
Kdtree(const rank_type &rank_, const key_compare &compare_)
void insert_rebalance(InputIterator first, InputIterator last)
Insert a serie of values in the container at once and rebalance the container after insertion...
std::ptrdiff_t random_access_iterator_distance(InputIterator first, InputIterator last, std::random_access_iterator_tag)
Kdtree< Rank, Key, Value, Compare, Alloc > Self
void set_root(node_ptr x)
dimension_type incr_dim(Rank rank, dimension_type node_dim)
Increment dimension node_dim, given rank.