summaryrefslogtreecommitdiff
path: root/STL/tree.h
diff options
context:
space:
mode:
Diffstat (limited to 'STL/tree.h')
-rw-r--r--STL/tree.h1068
1 files changed, 1068 insertions, 0 deletions
diff --git a/STL/tree.h b/STL/tree.h
new file mode 100644
index 00000000000..71568ec7807
--- /dev/null
+++ b/STL/tree.h
@@ -0,0 +1,1068 @@
+/*
+ *
+ * Copyright (c) 1994
+ * Hewlett-Packard Company
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation. Hewlett-Packard Company and Microsoft
+ * Corporation make no representations about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ *
+ */
+
+#ifndef TREE_H
+#define TREE_H
+
+/*
+
+Red-black tree class, designed for use in implementing STL
+associative containers (set, multiset, map, and multimap). The
+insertion and deletion algorithms are based on those in Cormen,
+Leiserson, and Rivest, Introduction to Algorithms (MIT Press, 1990),
+except that
+
+(1) the header cell is maintained with links not only to the root
+but also to the leftmost node of the tree, to enable constant time
+begin(), and to the rightmost node of the tree, to enable linear time
+performance when used with the generic set algorithms (set_union,
+etc.);
+
+(2) when a node being deleted has two children its successor node is
+relinked into its place, rather than copied, so that the only
+iterators invalidated are those referring to the deleted node.
+
+*/
+
+#include <algobase.h>
+#include <iterator.h>
+#include <function.h>
+#include <bool.h>
+#include <projectn.h>
+
+#ifndef rb_tree
+#define rb_tree rb_tree
+#endif
+
+/*
+ *Added by d:\Terris\convert.pl --begin--
+ */
+namespace std {
+/*
+ *Added by d:\Terris\convert.pl --end--
+ */
+
+template <class Key, class Value, class KeyOfValue, class Compare>
+class rb_tree {
+protected:
+ enum color_type {red, black};
+ typedef Allocator<void>::pointer void_pointer;
+ struct rb_tree_node;
+ friend rb_tree_node;
+ struct rb_tree_node {
+ color_type color_field;
+ void_pointer parent_link;
+ void_pointer left_link;
+ void_pointer right_link;
+ Value value_field;
+ };
+ static Allocator<rb_tree_node> rb_tree_node_allocator;
+ static Allocator<Value> value_allocator;
+public:
+ typedef Key key_type;
+ typedef Value value_type;
+ typedef Allocator<Value>::pointer pointer;
+ typedef Allocator<Value>::reference reference;
+ typedef Allocator<Value>::const_reference const_reference;
+ typedef Allocator<rb_tree_node> rb_tree_node_allocator_type;
+ typedef Allocator<rb_tree_node>::pointer link_type;
+ typedef Allocator<rb_tree_node>::size_type size_type;
+ typedef Allocator<rb_tree_node>::difference_type difference_type;
+protected:
+ size_type buffer_size() {
+ return rb_tree_node_allocator.init_page_size();
+ }
+ struct rb_tree_node_buffer;
+ friend rb_tree_node_buffer;
+ struct rb_tree_node_buffer {
+ void_pointer next_buffer;
+ link_type buffer;
+ };
+public:
+ typedef Allocator<rb_tree_node_buffer> buffer_allocator_type;
+ typedef Allocator<rb_tree_node_buffer>::pointer buffer_pointer;
+protected:
+ static Allocator<rb_tree_node_buffer> buffer_allocator;
+/*
+ * Changed by Terris
+ */
+ /*static*/ buffer_pointer buffer_list;
+ /*static*/ link_type free_list;
+ /*static*/ link_type next_avail;
+ /*static*/ link_type last;
+ void add_new_buffer() {
+ buffer_pointer tmp = buffer_allocator.allocate((size_type)1);
+ tmp->buffer = rb_tree_node_allocator.allocate(buffer_size());
+ tmp->next_buffer = buffer_list;
+ buffer_list = tmp;
+ next_avail = buffer_list->buffer;
+ last = next_avail + buffer_size();
+ }
+/*
+ * Changed by Terris
+ */
+ /*static*/ size_type number_of_trees;
+ void deallocate_buffers();
+ link_type get_node() {
+ link_type tmp = free_list;
+ return free_list ?
+ (free_list = (link_type)(free_list->right_link), tmp)
+ : (next_avail == last ? (add_new_buffer(), next_avail++)
+ : next_avail++);
+ // ugly code for inlining - avoids multiple returns
+ }
+ void put_node(link_type p) {
+ p->right_link = free_list;
+ free_list = p;
+ }
+protected:
+ link_type header;
+ link_type& root() { return parent(header); }
+ link_type& root() const { return parent(header); }
+ link_type& leftmost() { return left(header); }
+ link_type& leftmost() const { return left(header); }
+ link_type& rightmost() { return right(header); }
+ link_type& rightmost() const { return right(header); }
+ size_type node_count; // keeps track of size of tree
+ bool insert_always; // controls whether an element already in the
+ // tree is inserted again
+//public:
+ Compare key_compare;
+/*
+ * Changed by Terris
+ */
+ /*static*/ link_type NIL;
+
+ static link_type& left(link_type x) {
+ return (link_type&)((*x).left_link);
+ }
+ static link_type& right(link_type x) {
+ return (link_type&)((*x).right_link);
+ }
+ static link_type& parent(link_type x) {
+ return (link_type&)((*x).parent_link);
+ }
+ static reference value(link_type x) { return (*x).value_field; }
+ static Allocator<Key>::const_reference key(link_type x) {
+ return KeyOfValue()(value(x));
+ }
+ static color_type& color(link_type x) {
+ return (color_type&)(*x).color_field; }
+/*
+ * Changed by Terris
+ * Doesn't need to take "NIL" parameter because everyone who calls this
+ * uses links only from "this"
+ */
+ /*static*/ link_type minimum(link_type x) {
+ while (left(x) != NIL)
+ x = left(x);
+ return x;
+ }
+/*
+ * Changed by Terris
+ */
+ /*static*/ link_type maximum(link_type x) {
+ while (right(x) != NIL)
+ x = right(x);
+ return x;
+ }
+public:
+ class iterator;
+ friend iterator;
+ class const_iterator;
+ friend const_iterator;
+/*
+ * Terris comment: Here is where the iterator class starts.
+ */
+ class iterator : public bidirectional_iterator<Value, difference_type> {
+ friend class rb_tree<Key, Value, KeyOfValue, Compare>;
+ friend class const_iterator;
+/*
+ * Added by Terris
+ */
+ link_type NIL;
+
+/*
+ friend bool operator==(const iterator& x, const iterator& y) {
+ return x.node == y.node;
+ }
+*/
+ protected:
+ link_type node;
+ iterator(link_type x, link_type NIL) : node(x), NIL(NIL) {}
+ public:
+ iterator() {}
+ bool operator==(const iterator& y) const { return node == y.node; }
+ reference operator*() const { return value(node); }
+ iterator& operator++() {
+ if (right(node) != NIL) {
+ node = right(node);
+ while (left(node) != NIL)
+ node = left(node);
+ } else {
+ link_type y = parent(node);
+ while (node == right(y)) {
+ node = y;
+ y = parent(y);
+ }
+ if (right(node) != y) // necessary because of rightmost
+ node = y;
+ }
+ return *this;
+ }
+ iterator operator++(int) {
+ iterator tmp = *this;
+ ++*this;
+ return tmp;
+ }
+ iterator& operator--() {
+ if (color(node) == red && parent(parent(node)) == node)
+ // check for header
+ node = right(node); // return rightmost
+ else if (left(node) != NIL) {
+ link_type y = left(node);
+ while (right(y) != NIL)
+ y = right(y);
+ node = y;
+ } else {
+ link_type y = parent(node);
+ while (node == left(y)) {
+ node = y;
+ y = parent(y);
+ }
+ node = y;
+ }
+ return *this;
+ }
+ iterator operator--(int) {
+ iterator tmp = *this;
+ --*this;
+ return tmp;
+ }
+ };
+/*
+ * Terris comment: Iterator class ends here
+ * Terris comment: Const Iterator class starts here
+ */
+ class const_iterator
+ : public bidirectional_iterator<Value,difference_type> {
+ friend class rb_tree<Key, Value, KeyOfValue, Compare>;
+ friend class iterator;
+/*
+ friend bool operator==(const const_iterator& x, const const_iterator& y) {
+ return x.node == y.node;
+ }
+*/
+/*
+ * Added by Terris
+ */
+ link_type NIL;
+
+ protected:
+ link_type node;
+ const_iterator(link_type x, link_type NIL) : node(x), NIL(NIL) {}
+ public:
+ const_iterator() {}
+ const_iterator(const iterator& x) : node(x.node) {}
+ bool operator==(const const_iterator& y) const {
+ return node == y.node;
+ }
+ bool operator!=(const const_iterator& y) const {
+ return node != y.node;
+ }
+ const_reference operator*() const { return value(node); }
+ const_iterator& operator++() {
+ if (right(node) != NIL) {
+ node = right(node);
+ while (left(node) != NIL)
+ node = left(node);
+ } else {
+ link_type y = parent(node);
+ while (node == right(y)) {
+ node = y;
+ y = parent(y);
+ }
+ if (right(node) != y) // necessary because of rightmost
+ node = y;
+ }
+ return *this;
+ }
+ const_iterator operator++(int) {
+ const_iterator tmp = *this;
+ ++*this;
+ return tmp;
+ }
+ const_iterator& operator--() {
+ if (color(node) == red && parent(parent(node)) == node)
+ // check for header
+ node = right(node); // return rightmost
+ else if (left(node) != NIL) {
+ link_type y = left(node);
+ while (right(y) != NIL)
+ y = right(y);
+ node = y;
+ } else {
+ link_type y = parent(node);
+ while (node == left(y)) {
+ node = y;
+ y = parent(y);
+ }
+ node = y;
+ }
+ return *this;
+ }
+ const_iterator operator--(int) {
+ const_iterator tmp = *this;
+ --*this;
+ return tmp;
+ }
+ };
+/*
+ * Terris comment: const_iterator ends here
+ */
+ typedef reverse_bidirectional_iterator<iterator, value_type, reference,
+ difference_type>
+ reverse_iterator;
+ typedef reverse_bidirectional_iterator<const_iterator, value_type,
+ const_reference, difference_type>
+ const_reverse_iterator;
+private:
+ iterator __insert(link_type x, link_type y, const value_type& v);
+/*
+ * Changed by Terris
+ */
+ link_type __copy(link_type x, link_type p, link_type nil);
+ void __erase(link_type x);
+ void init() {
+ ++number_of_trees;
+ if ( NIL == 0 ) {
+ NIL = get_node();
+ color(NIL) = black;
+ parent(NIL) = 0;
+ left(NIL) = 0;
+ right(NIL) = 0;
+ }
+ header = get_node();
+ color(header) = red; // used to distinguish header from root,
+ // in iterator.operator++
+ root() = NIL;
+ leftmost() = header;
+ rightmost() = header;
+ }
+public:
+
+// allocation/deallocation
+
+/*
+ * Changed by Terris
+ */
+ rb_tree(const Compare& comp = Compare(), bool always = true)
+ : node_count(0), key_compare(comp), insert_always(always), free_list(0), buffer_list(0), next_avail(0),
+ last(0), number_of_trees(0), NIL(0) {
+ init();
+ }
+/*
+ * Changed by Terris
+ */
+ rb_tree(const value_type* first, const value_type* last,
+ const Compare& comp = Compare(), bool always = true)
+ : node_count(0), key_compare(comp), insert_always(always), free_list(0),
+ buffer_list(0), next_avail(0), last(0), number_of_trees(0), NIL(0) {
+ init();
+ insert(first, last);
+ }
+/*
+ * Changed by Terris
+ */
+ rb_tree(const rb_tree<Key, Value, KeyOfValue, Compare>& x,
+ bool always = true) : node_count(x.node_count),
+ key_compare(x.key_compare), insert_always(always), free_list(0),
+ buffer_list(0), next_avail(0), last(0), number_of_trees(0),
+ NIL( 0 ) {
+/*
+ * Added by Terris
+ */
+ init();
+/*
+ * Changed by Terris
+ */
+ // ++number_of_trees;
+ // header = get_node();
+ // color(header) = red;
+/*
+ * Changed by Terris
+ */
+ root() = __copy(x.root(), header, x.NIL);
+ if (root() == NIL) {
+ leftmost() = header;
+ rightmost() = header;
+ } else {
+ leftmost() = minimum(root());
+ rightmost() = maximum(root());
+ }
+ }
+ ~rb_tree() {
+ erase(begin(), end());
+ put_node(header);
+ if (--number_of_trees == 0) {
+ put_node(NIL);
+ NIL = 0;
+ deallocate_buffers();
+ free_list = 0;
+ next_avail = 0;
+ last = 0;
+ }
+ }
+ rb_tree<Key, Value, KeyOfValue, Compare>&
+ operator=(const rb_tree<Key, Value, KeyOfValue, Compare>& x);
+
+// accessors:
+
+ Compare key_comp() const { return key_compare; }
+/*
+ * Changed by Terris
+ */
+ iterator begin() { return iterator(leftmost(), NIL); }
+/*
+ * Changed by Terris
+ */
+ const_iterator begin() const { return const_iterator(leftmost(), NIL); }
+/*
+ * Changed by Terris
+ */
+ iterator end() { return iterator(header, NIL); }
+/*
+ * Changed by Terris
+ */
+ const_iterator end() const { return const_iterator(header, NIL); }
+ reverse_iterator rbegin() { return reverse_iterator(end()); }
+ const_reverse_iterator rbegin() const {
+ return const_reverse_iterator(end());
+ }
+ reverse_iterator rend() { return reverse_iterator(begin()); }
+ const_reverse_iterator rend() const {
+ return const_reverse_iterator(begin());
+ }
+ bool empty() const { return node_count == 0; }
+ size_type size() const { return node_count; }
+ size_type max_size() const {
+ return rb_tree_node_allocator.max_size();
+ }
+ void swap(rb_tree<Key, Value, KeyOfValue, Compare>& t) {
+ std::swap(header, t.header);
+ std::swap(node_count, t.node_count);
+ std::swap(insert_always, t.insert_always);
+ std::swap(key_compare, t.key_compare);
+ }
+
+// insert/erase
+
+ typedef pair<iterator, bool> pair_iterator_bool;
+ // typedef done to get around compiler bug
+ pair_iterator_bool insert(const value_type& x);
+ iterator insert(iterator position, const value_type& x);
+ void insert(iterator first, iterator last);
+ void insert(const value_type* first, const value_type* last);
+ void erase(iterator position);
+ size_type erase(const key_type& x);
+ void erase(iterator first, iterator last);
+ void erase(const key_type* first, const key_type* last);
+
+// set operations:
+
+ iterator find(const key_type& x);
+ const_iterator find(const key_type& x) const;
+ size_type count(const key_type& x) const;
+ iterator lower_bound(const key_type& x);
+ const_iterator lower_bound(const key_type& x) const;
+ iterator upper_bound(const key_type& x);
+ const_iterator upper_bound(const key_type& x) const;
+ typedef pair<iterator, iterator> pair_iterator_iterator;
+ // typedef done to get around compiler bug
+ pair_iterator_iterator equal_range(const key_type& x);
+ typedef pair<const_iterator, const_iterator> pair_citerator_citerator;
+ // typedef done to get around compiler bug
+ pair_citerator_citerator equal_range(const key_type& x) const;
+ inline void rotate_left(link_type x);
+ inline void rotate_right(link_type x);
+};
+
+/*
+ * Added by Terris
+ */
+#if 0
+template <class Key, class Value, class KeyOfValue, class Compare>
+rb_tree<Key, Value, KeyOfValue, Compare>::buffer_pointer
+ rb_tree<Key, Value, KeyOfValue, Compare>::buffer_list = 0;
+
+template <class Key, class Value, class KeyOfValue, class Compare>
+rb_tree<Key, Value, KeyOfValue, Compare>::link_type
+ rb_tree<Key, Value, KeyOfValue, Compare>::free_list = 0;
+
+template <class Key, class Value, class KeyOfValue, class Compare>
+rb_tree<Key, Value, KeyOfValue, Compare>::link_type
+ rb_tree<Key, Value, KeyOfValue, Compare>::next_avail = 0;
+
+template <class Key, class Value, class KeyOfValue, class Compare>
+rb_tree<Key, Value, KeyOfValue, Compare>::link_type
+ rb_tree<Key, Value, KeyOfValue, Compare>::last = 0;
+
+template <class Key, class Value, class KeyOfValue, class Compare>
+rb_tree<Key, Value, KeyOfValue, Compare>::size_type
+ rb_tree<Key, Value, KeyOfValue, Compare>::number_of_trees = 0;
+/*
+ * Added by Terris
+ */
+#endif
+
+template <class Key, class Value, class KeyOfValue, class Compare>
+rb_tree<Key, Value, KeyOfValue, Compare>::rb_tree_node_allocator_type
+ rb_tree<Key, Value, KeyOfValue, Compare>::rb_tree_node_allocator;
+
+template <class Key, class Value, class KeyOfValue, class Compare>
+Allocator<Value> rb_tree<Key, Value, KeyOfValue, Compare>::value_allocator;
+
+template <class Key, class Value, class KeyOfValue, class Compare>
+rb_tree<Key, Value, KeyOfValue, Compare>::buffer_allocator_type
+ rb_tree<Key, Value, KeyOfValue, Compare>::buffer_allocator;
+
+/* Added by Terris
+ */
+#if 0
+template <class Key, class Value, class KeyOfValue, class Compare>
+rb_tree<Key, Value, KeyOfValue, Compare>::link_type
+ rb_tree<Key, Value, KeyOfValue, Compare>::NIL = 0;
+#endif
+
+template <class Key, class Value, class KeyOfValue, class Compare>
+void rb_tree<Key, Value, KeyOfValue, Compare>::deallocate_buffers() {
+ while (buffer_list) {
+ buffer_pointer tmp = buffer_list;
+ buffer_list = (buffer_pointer)(buffer_list->next_buffer);
+ rb_tree_node_allocator.deallocate(tmp->buffer);
+ buffer_allocator.deallocate(tmp);
+ }
+}
+
+template <class Key, class Value, class KeyOfValue, class Compare>
+inline bool operator==(const rb_tree<Key, Value, KeyOfValue, Compare>& x,
+ const rb_tree<Key, Value, KeyOfValue, Compare>& y) {
+ return x.size() == y.size() && equal(x.begin(), x.end(), y.begin());
+}
+
+template <class Key, class Value, class KeyOfValue, class Compare>
+inline bool operator<(const rb_tree<Key, Value, KeyOfValue, Compare>& x,
+ const rb_tree<Key, Value, KeyOfValue, Compare>& y) {
+ return lexicographical_compare(x.begin(), x.end(), y.begin(), y.end());
+}
+
+template <class Key, class Value, class KeyOfValue, class Compare>
+rb_tree<Key, Value, KeyOfValue, Compare>&
+rb_tree<Key, Value, KeyOfValue, Compare>::
+operator=(const rb_tree<Key, Value, KeyOfValue, Compare>& x) {
+ if (this != &x) {
+ // can't be done as in list because Key may be a constant type
+ erase(begin(), end());
+/*
+ * Changed by Terris
+ */
+ root() = __copy(x.root(), header, x.NIL);
+ if (root() == NIL) {
+ leftmost() = header;
+ rightmost() = header;
+ } else {
+ leftmost() = minimum(root());
+ rightmost() = maximum(root());
+ }
+ node_count = x.node_count;
+ }
+ return *this;
+}
+
+template <class Key, class Value, class KeyOfValue, class Compare>
+rb_tree<Key, Value, KeyOfValue, Compare>::iterator
+rb_tree<Key, Value, KeyOfValue, Compare>::
+__insert(link_type x, link_type y, const Value& v) {
+ ++node_count;
+ link_type z = get_node();
+ construct(value_allocator.address(value(z)), v);
+ if (y == header || x != NIL || key_compare(KeyOfValue()(v), key(y))) {
+ left(y) = z; // also makes leftmost() = z when y == header
+ if (y == header) {
+ root() = z;
+ rightmost() = z;
+ } else if (y == leftmost())
+ leftmost() = z; // maintain leftmost() pointing to minimum node
+ } else {
+ right(y) = z;
+ if (y == rightmost())
+ rightmost() = z; // maintain rightmost() pointing to maximum node
+ }
+ parent(z) = y;
+ left(z) = NIL;
+ right(z) = NIL;
+ x = z; // recolor and rebalance the tree
+ color(x) = red;
+ while (x != root() && color(parent(x)) == red)
+ if (parent(x) == left(parent(parent(x)))) {
+ y = right(parent(parent(x)));
+ if (color(y) == red) {
+ color(parent(x)) = black;
+ color(y) = black;
+ color(parent(parent(x))) = red;
+ x = parent(parent(x));
+ } else {
+ if (x == right(parent(x))) {
+ x = parent(x);
+ rotate_left(x);
+ }
+ color(parent(x)) = black;
+ color(parent(parent(x))) = red;
+ rotate_right(parent(parent(x)));
+ }
+ } else {
+ y = left(parent(parent(x)));
+ if (color(y) == red) {
+ color(parent(x)) = black;
+ color(y) = black;
+ color(parent(parent(x))) = red;
+ x = parent(parent(x));
+ } else {
+ if (x == left(parent(x))) {
+ x = parent(x);
+ rotate_right(x);
+ }
+ color(parent(x)) = black;
+ color(parent(parent(x))) = red;
+ rotate_left(parent(parent(x)));
+ }
+ }
+ color(root()) = black;
+ return iterator(z, NIL);
+}
+
+template <class Key, class Value, class KeyOfValue, class Compare>
+rb_tree<Key, Value, KeyOfValue, Compare>::pair_iterator_bool
+rb_tree<Key, Value, KeyOfValue, Compare>::insert(const Value& v) {
+ link_type y = header;
+ link_type x = root();
+ bool comp = true;
+ while (x != NIL) {
+ y = x;
+ comp = key_compare(KeyOfValue()(v), key(x));
+ x = comp ? left(x) : right(x);
+ }
+ if (insert_always)
+ return pair_iterator_bool(__insert(x, y, v), true);
+ iterator j = iterator(y, NIL);
+ if (comp)
+ if (j == begin())
+ return pair_iterator_bool(__insert(x, y, v), true);
+ else
+ --j;
+ if (key_compare(key(j.node), KeyOfValue()(v)))
+ return pair_iterator_bool(__insert(x, y, v), true);
+ return pair_iterator_bool(j, false);
+}
+
+template <class Key, class Value, class KeyOfValue, class Compare>
+rb_tree<Key, Value, KeyOfValue, Compare>::iterator
+rb_tree<Key, Value, KeyOfValue, Compare>::insert(iterator position,
+ const Value& v) {
+ if (position == iterator(begin()))
+ if (size() > 0 && key_compare(KeyOfValue()(v), key(position.node)))
+ return __insert(position.node, position.node, v);
+ // first argument just needs to be non-NIL
+ else
+ return insert(v).first;
+ else if (position == iterator(end()))
+ if (key_compare(key(rightmost()), KeyOfValue()(v)))
+ return __insert(NIL, rightmost(), v);
+ else
+ return insert(v).first;
+ else {
+ iterator before = --position;
+ if (key_compare(key(before.node), KeyOfValue()(v))
+ && key_compare(KeyOfValue()(v), key(position.node)))
+ if (right(before.node) == NIL)
+ return __insert(NIL, before.node, v);
+ else
+ return __insert(position.node, position.node, v);
+ // first argument just needs to be non-NIL
+ else
+ return insert(v).first;
+ }
+}
+
+template <class Key, class Value, class KeyOfValue, class Compare>
+void rb_tree<Key, Value, KeyOfValue, Compare>::insert(iterator first,
+ iterator last) {
+ while (first != last) insert(*first++);
+}
+
+template <class Key, class Value, class KeyOfValue, class Compare>
+void rb_tree<Key, Value, KeyOfValue, Compare>::insert(const Value* first,
+ const Value* last) {
+ while (first != last) insert(*first++);
+}
+
+template <class Key, class Value, class KeyOfValue, class Compare>
+void rb_tree<Key, Value, KeyOfValue, Compare>::erase(iterator position) {
+ link_type z = position.node;
+ link_type y = z;
+ link_type x;
+ if (left(y) == NIL)
+ x = right(y);
+ else
+ if (right(y) == NIL)
+ x = left(y);
+ else {
+ y = right(y);
+ while (left(y) != NIL)
+ y = left(y);
+ x = right(y);
+ }
+ if (y != z) { // relink y in place of z
+ parent(left(z)) = y;
+ left(y) = left(z);
+ if (y != right(z)) {
+ parent(x) = parent(y); // possibly x == NIL
+ left(parent(y)) = x; // y must be a left child
+ right(y) = right(z);
+ parent(right(z)) = y;
+ } else
+ parent(x) = y; // needed in case x == NIL
+ if (root() == z)
+ root() = y;
+ else if (left(parent(z)) == z)
+ left(parent(z)) = y;
+ else
+ right(parent(z)) = y;
+ parent(y) = parent(z);
+ std::swap(color(y), color(z));
+ std::swap(y, z);
+ // y points to node to be actually deleted,
+ // z points to old z's former successor
+ } else { // y == z
+ parent(x) = parent(y); // possibly x == NIL
+ if (root() == z)
+ root() = x;
+ else
+ if (left(parent(z)) == z)
+ left(parent(z)) = x;
+ else
+ right(parent(z)) = x;
+ if (leftmost() == z)
+ if (right(z) == NIL) // left(z) must be NIL also
+ leftmost() = parent(z);
+ // makes leftmost() == header if z == root()
+ else
+ leftmost() = minimum(x);
+ if (rightmost() == z)
+ if (left(z) == NIL) // right(z) must be NIL also
+ rightmost() = parent(z);
+ // makes rightmost() == header if z == root()
+ else // x == left(z)
+ rightmost() = maximum(x);
+ }
+ if (color(y) != red) {
+ while (x != root() && color(x) == black)
+ if (x == left(parent(x))) {
+ link_type w = right(parent(x));
+ if (color(w) == red) {
+ color(w) = black;
+ color(parent(x)) = red;
+ rotate_left(parent(x));
+ w = right(parent(x));
+ }
+ if (color(left(w)) == black && color(right(w)) == black) {
+ color(w) = red;
+ x = parent(x);
+ } else {
+ if (color(right(w)) == black) {
+ color(left(w)) = black;
+ color(w) = red;
+ rotate_right(w);
+ w = right(parent(x));
+ }
+ color(w) = color(parent(x));
+ color(parent(x)) = black;
+ color(right(w)) = black;
+ rotate_left(parent(x));
+ break;
+ }
+ } else { // same as then clause with "right" and "left" exchanged
+ link_type w = left(parent(x));
+ if (color(w) == red) {
+ color(w) = black;
+ color(parent(x)) = red;
+ rotate_right(parent(x));
+ w = left(parent(x));
+ }
+ if (color(right(w)) == black && color(left(w)) == black) {
+ color(w) = red;
+ x = parent(x);
+ } else {
+ if (color(left(w)) == black) {
+ color(right(w)) = black;
+ color(w) = red;
+ rotate_left(w);
+ w = left(parent(x));
+ }
+ color(w) = color(parent(x));
+ color(parent(x)) = black;
+ color(left(w)) = black;
+ rotate_right(parent(x));
+ break;
+ }
+ }
+ color(x) = black;
+ }
+ destroy(value_allocator.address(value(y)));
+ put_node(y);
+ --node_count;
+}
+
+template <class Key, class Value, class KeyOfValue, class Compare>
+rb_tree<Key, Value, KeyOfValue, Compare>::size_type
+rb_tree<Key, Value, KeyOfValue, Compare>::erase(const Key& x) {
+ pair_iterator_iterator p = equal_range(x);
+ size_type n = 0;
+ distance(p.first, p.second, n);
+ erase(p.first, p.second);
+ return n;
+}
+
+template <class Key, class Value, class KeyOfValue, class Compare>
+rb_tree<Key, Value, KeyOfValue, Compare>::link_type
+/*
+ * Changed by Terris
+ */
+rb_tree<Key, Value, KeyOfValue, Compare>::__copy(link_type x, link_type p, link_type xNIL) {
+ // structural copy
+ link_type r = x;
+ while (x != xNIL) {
+ link_type y = get_node();
+ if (r == x) r = y; // save for return value
+ construct(value_allocator.address(value(y)), value(x));
+ left(p) = y;
+ parent(y) = p;
+ color(y) = color(x);
+/*
+ * Changed by Terris
+ */
+ right(y) = __copy(right(x), y, xNIL);
+ p = y;
+ x = left(x);
+ }
+ left(p) = NIL;
+/*
+ * Changed by Terris
+ */
+ return r == xNIL ? NIL : r;
+}
+
+template <class Key, class Value, class KeyOfValue, class Compare>
+void rb_tree<Key, Value, KeyOfValue, Compare>::__erase(link_type x) {
+ // erase without rebalancing
+ while (x != NIL) {
+ __erase(right(x));
+ link_type y = left(x);
+ destroy(value_allocator.address(value(x)));
+ put_node(x);
+ x = y;
+ }
+}
+
+template <class Key, class Value, class KeyOfValue, class Compare>
+void rb_tree<Key, Value, KeyOfValue, Compare>::erase(iterator first,
+ iterator last) {
+ if (first == begin() && last == end() && node_count != 0) {
+ __erase(root());
+ leftmost() = header;
+ root() = NIL;
+ rightmost() = header;
+ node_count = 0;
+ } else
+ while (first != last) erase(first++);
+}
+
+template <class Key, class Value, class KeyOfValue, class Compare>
+void rb_tree<Key, Value, KeyOfValue, Compare>::erase(const Key* first,
+ const Key* last) {
+ while (first != last) erase(*first++);
+}
+
+template <class Key, class Value, class KeyOfValue, class Compare>
+rb_tree<Key, Value, KeyOfValue, Compare>::iterator
+rb_tree<Key, Value, KeyOfValue, Compare>::find(const Key& k) {
+ link_type y = header;
+ link_type x = root();
+ bool comp = false;
+ while (x != NIL) {
+ y = x;
+ comp = key_compare(key(x), k);
+ x = comp ? right(x) : left(x);
+ }
+ iterator j = iterator(y, NIL);
+ if (comp) ++j;
+ return (j == end() || key_compare(k, key(j.node))) ? end() : j;
+}
+
+template <class Key, class Value, class KeyOfValue, class Compare>
+rb_tree<Key, Value, KeyOfValue, Compare>::const_iterator
+rb_tree<Key, Value, KeyOfValue, Compare>::find(const Key& k) const {
+ link_type y = header;
+ link_type x = root();
+ bool comp = false;
+ while (x != NIL) {
+ y = x;
+ comp = key_compare(key(x), k);
+ x = comp ? right(x) : left(x);
+ }
+ const_iterator j = const_iterator(y, NIL);
+ if (comp) ++j;
+ return (j == end() || key_compare(k, key(j.node))) ? end() : j;
+}
+
+template <class Key, class Value, class KeyOfValue, class Compare>
+rb_tree<Key, Value, KeyOfValue, Compare>::size_type
+rb_tree<Key, Value, KeyOfValue, Compare>::count(const Key& k) const {
+ pair<const_iterator, const_iterator> p = equal_range(k);
+ size_type n = 0;
+ distance(p.first, p.second, n);
+ return n;
+}
+
+template <class Key, class Value, class KeyOfValue, class Compare>
+rb_tree<Key, Value, KeyOfValue, Compare>::iterator
+rb_tree<Key, Value, KeyOfValue, Compare>::lower_bound(const Key& k) {
+ link_type y = header;
+ link_type x = root();
+ bool comp = false;
+ while (x != NIL) {
+ y = x;
+ comp = key_compare(key(x), k);
+ x = comp ? right(x) : left(x);
+ }
+ iterator j = iterator(y, NIL);
+ return comp ? ++j : j;
+}
+
+template <class Key, class Value, class KeyOfValue, class Compare>
+rb_tree<Key, Value, KeyOfValue, Compare>::const_iterator
+rb_tree<Key, Value, KeyOfValue, Compare>::lower_bound(const Key& k) const {
+ link_type y = header;
+ link_type x = root();
+ bool comp = false;
+ while (x != NIL) {
+ y = x;
+ comp = key_compare(key(x), k);
+ x = comp ? right(x) : left(x);
+ }
+ const_iterator j = const_iterator(y, NIL);
+ return comp ? ++j : j;
+}
+
+template <class Key, class Value, class KeyOfValue, class Compare>
+rb_tree<Key, Value, KeyOfValue, Compare>::iterator
+rb_tree<Key, Value, KeyOfValue, Compare>::upper_bound(const Key& k) {
+ link_type y = header;
+ link_type x = root();
+ bool comp = true;
+ while (x != NIL) {
+ y = x;
+ comp = key_compare(k, key(x));
+ x = comp ? left(x) : right(x);
+ }
+ iterator j = iterator(y, NIL);
+ return comp ? j : ++j;
+}
+
+template <class Key, class Value, class KeyOfValue, class Compare>
+rb_tree<Key, Value, KeyOfValue, Compare>::const_iterator
+rb_tree<Key, Value, KeyOfValue, Compare>::upper_bound(const Key& k) const {
+ link_type y = header;
+ link_type x = root();
+ bool comp = true;
+ while (x != NIL) {
+ y = x;
+ comp = key_compare(k, key(x));
+ x = comp ? left(x) : right(x);
+ }
+ const_iterator j = const_iterator(y, NIL);
+ return comp ? j : ++j;
+}
+
+
+template <class Key, class Value, class KeyOfValue, class Compare>
+rb_tree<Key, Value, KeyOfValue, Compare>::pair_iterator_iterator
+rb_tree<Key, Value, KeyOfValue, Compare>::equal_range(const Key& k) {
+ return pair_iterator_iterator(lower_bound(k), upper_bound(k));
+}
+
+template <class Key, class Value, class KeyOfValue, class Compare>
+rb_tree<Key, Value, KeyOfValue, Compare>::pair_citerator_citerator
+rb_tree<Key, Value, KeyOfValue, Compare>::equal_range(const Key& k) const {
+ return pair_citerator_citerator(lower_bound(k), upper_bound(k));
+}
+
+template <class Key, class Value, class KeyOfValue, class Compare>
+inline void
+rb_tree<Key, Value, KeyOfValue, Compare>::rotate_left(link_type x) {
+ link_type y = right(x);
+ right(x) = left(y);
+ if (left(y) != NIL)
+ parent(left(y)) = x;
+ parent(y) = parent(x);
+ if (x == root())
+ root() = y;
+ else if (x == left(parent(x)))
+ left(parent(x)) = y;
+ else
+ right(parent(x)) = y;
+ left(y) = x;
+ parent(x) = y;
+}
+
+template <class Key, class Value, class KeyOfValue, class Compare>
+inline void
+rb_tree<Key, Value, KeyOfValue, Compare>::rotate_right(link_type x) {
+ link_type y = left(x);
+ left(x) = right(y);
+ if (right(y) != NIL)
+ parent(right(y)) = x;
+ parent(y) = parent(x);
+ if (x == root())
+ root() = y;
+ else if (x == right(parent(x)))
+ right(parent(x)) = y;
+ else
+ left(parent(x)) = y;
+ right(y) = x;
+ parent(x) = y;
+}
+
+
+/*
+ *Added by d:\Terris\convert.pl --begin--
+ */
+}
+/*
+ *Added by d:\Terris\convert.pl --end--
+ */
+
+#endif