Figure 3: The interval tree template class itree
#ifndef ITREE_H_ #define ITREE_H_ #include <vector> #include <set> #include <assert.h> #include <algorithm> #include <iterator> template<class T, class A = std::allocator<T> > class itree { public: typedef T invl_type; typedef T::range_type range_type; typedef std::vector<invl_type, A> invl_vec; typedef invl_vec::iterator iterator; typedef invl_vec::const_iterator const_iterator; // other types derived from invl_vec omitted ... private: typedef struct node_tag // Interval tree nodes { range_type discrim; // discriminant int start; // starting offset in AL and DH int size; // number of entris in AL and DH struct node_tag *left; // left subtree struct node_tag *right; // right subtree } node; public: ... // query iterator definition omitted ... // functions forwarded to std::vector omitted // Interval tree specific functionality follows itree() : root(NULL) {} ~itree() { deconstruct(); } void deconstruct(void) // reverts initialization mode { delete_tree(root); root = NULL; } void delete_tree(node *cur_node) { // delete nodes in tree if (cur_node != NULL) { delete_tree(cur_node->left); // left tree // recursively delete_tree(cur_node->right); // right tree // recursively delete cur_node; } } bool constructed() const { return root != NULL; } // build the interval tree structure and // put the container into query mode itree const& construct(void) { std::vector<range_type> values; std::vector<bool> flags(invls.size(), false); int num_al_dh = 0; extract_values(values); al.resize(invls.size()); dh.resize(invls.size()); root = construct_tree(values, flags, num_al_dh, 0, values.size() - 1); return *this; } ... // extract_values function definition omitted // recursively construct the tree node* construct_tree(const std::vector<range_type>& values, std::vector<bool>& flags, int& num_al_dh, int start, int end) { int discrim_pos; range_type discrim; int list_start, list_size; node *root, *left, *right; bool continue_left = false; bool continue_right = false; root = left = right = NULL; if (start > end) return root; discrim_pos = (start + end) / 2; discrim = values[discrim_pos]; list_start = num_al_dh; list_size = 0; for (int i = 0; i < invls.size(); i++) { if (flags[i]) continue; if ((invls[i].low() <= discrim) && (invls[i].high() >= discrim)) { al[num_al_dh] = &(invls[i]); dh[num_al_dh] = &(invls[i]); num_al_dh++; list_size++; flags[i] = true; } if ((invls[i].low() < discrim) && (invls[i].high() < discrim)) continue_left = true; if ((invls[i].low() > discrim) && (invls[i].high() > discrim)) continue_right = true; } // see if left and/or right subtree needs to be built if (continue_left && (start <= (discrim_pos - 1))) left = construct_tree(values, flags, num_al_dh, start, discrim_pos - 1); if (continue_right && ((discrim_pos + 1) <= end)) right = construct_tree(values, flags, num_al_dh, discrim_pos + 1, end); // this node is needed only if thre are entries in the // AL/DH list or the left or right subtree exists. if ((list_size > 0) || (left != NULL) || (right != NULL)) { std::sort(&(al[list_start]), &(al[list_start + list_size]), comp_for_al); std::sort(&(dh[list_start]), &(dh[list_start + list_size]), comp_for_dh); root = new node; root->left = left; root->right = right; root->discrim = discrim; root->start = list_start; root->size = list_size; } return root; } ... // comparison functions for sorting AL and DL omitted query_iterator qbegin(range_type x) { assert(constructed()); query_iterator it(root, 0, x, &al, &dh); it.init_node(); return it; } query_iterator qend(range_type x) { assert(constructed()); query_iterator it(NULL, 0, x, NULL, NULL); return it; } private: invl_vec invls; // vector of intervals std::vector<invl_type*> al, dh; // vectors of interval ptrs node *root; // Interval tree root node }; #endif // ITREE_H_