Document No.
WG21/N2101=J16/06-0171
Date
2006-11-05
Project
Programming Language C++
Reply to
Bernhard Reiter <ockham@gmx.net>,
René Rivera <rrivera@acm.org>

Hierarchical Data Structures and Related Concepts for the C++ Standard Library

Bernhard Reiter and René Rivera

Table of Contents

Introduction

This paper proposes addition of library components covering tree structures and related concepts to the C++ Standard Library Technical Report 2. The proposal is based on work towards a Boost tree component library (see https://boost-consulting.com:8443/trac/soc/wiki/tree).

The library strives to cover many of the relevant aspects within the vast field linked to the notion of trees in computer science.

Motivation and Scope

Why is this important?

This proposal is motivated by the wish to establish methods of dealing with hierarchical data structures in a manner that is similar to that of the STL for linear ones. That is, it seeks to provide clear, straight-forward, versatile and comprehensive concepts, data structures and algorithms for trees and related structures that allow efficient implementation while not exposing implementation details.

In particular, this proposal strives to unite types of hierarchical data structures that have historically been treated separately, although there is arguably good reason to view their role for algorithms as different aspects of common underlying concepts. Formally, this proposal's desired scope is covering all rooted ordered connected acyclic graphs.

What kinds of problems does it address, and what kinds of programmers is it intended to support?

Existing tree implementations as listed in the References section as well as the number of posts on C++ related newsgroups give an evidence of very general, high interest in tree and related data structures. Formalization of how to deal with hierarchical data structures seems to be relevant as programmers of any level of skill working in any given field is likely to need such a structure at one point.

Is it based on existing practice?

No; this proposal originates in an effort to create a generic tree container component for Boost in the course of Google Summer of Code™ 2006, so at the time of this writing, implementation work is still unfinished and, however inspired by and striving to avoid past issues and such ones arising from current implementation efforts (see below) it is, it has not been used in practice yet.

Is there a reference implementation?

Yes; the current state is available from svn from https://www.boost-consulting.com:8443/svn/main/boost/soc/2006/tree/trunk. Alternatively, the source code can be viewed in a web browser at https://boost-consulting.com:8443/trac/soc/browser/boost/soc/2006/tree.

Impact on the Standard

What does it depend on, and what depends on it?

It depends on some standard library components, such as std::allocator which is used as the default allocator template argument at some points. Concepts like allocators or iterators are reused and in some cases adapted.

Is it a pure extension, or does it require changes to standard components?

Most of the proposed library is a pure extension.

Some extensions <algorithm> and some extensions to <iterator> are proposed.

Additionally, while not proposed herein, it has sometimes been suggested to add a template parameter to the STL associative containers set, multiset, map, and multimap (and possibly an argument to their constructors) specifying a policy for storing elements, or, more concretely, what tree. The balancers presented in this proposal would lend themselves to such use. Indicating what type of balanced hierarchy to use for associative containers would create some amount of symmetry to TR1's unordered containers that allow specification of a hash functor; it is however a momentous decision in which position to put such a parameter. The same position as for unordered containers (before the comparison functor) would require changes in existing code; making it the last parameter (after the allocator) would allow existing code to remain unchanged, but seems somewhat irritating when compared to unordered containers.

Can it be implemented using today's compilers, or does it require language features that will only be available as part of C++0x?

It can be, and partly has been, implemented with today's compilers.

Note that it might be worthwhile to investigate if the present Container concept should be modified so that it only covers the requirements as of paragraph 2 of section [tr.hierarchy.req] of this proposal, which correspond to the current Container concept with the exception of any expressions that implicitly assume linear internal structure and outsource those to a "Linear Container" concept as similarly formalized in the Boost Range concept (http://boost.org/libs/range/doc/range.html) externally to the Standard.

Important Design Decisions

Why did you choose the specific design that you did?

One of the most important assets of the present design is the cursor concept as a hierarchical continuation to the STL's iterator concept, and the externally defined range concept. Among their benefits, cursors allow to handle both client data access, by dereference, and subtree access while hiding the normally underlying node structure and providing a uniform interface to algorithms that are thus enabled to deal with a number of different kinds of trees. On the other hand, this abstraction achieves independence of implementation details, such as nodes for storage in many cases, allowing the underlying concepts to be applicable to other possible implementations as well.

What alternatives did you consider, and what are the tradeoffs?

Trees of trees
Trees, being recursively defined data structures, seem to somewhat lend themselves to recursive implementation, i.e. declaring them in a way so they consist of a client value part and a certain number of trees in turn (as e.g. in case of [haas]). Such an approach would allow for uniform treatment of the subtrees, but would duplicate allocators and imply structure that need not be present. The tree, like existing STL containers, should be responsible for data representation and storage.
Augmentors/balancers as policies
Inspired by [austern] and [dreizin], the original approach undertaken when working on the reference implementation was to pass policy template arguments to template class binary_tree. While reproducing the (otherwise unbalanced) tree/cursor interface seemed logical at first, it turned out that this was conceptually not entirely clean, as e.g. it preferred one type of linear order, namely inorder, over the others by putting such strong focus on inorder-invariant balancing and its possible applications; also, balancing and augmenting metadata would inevitably have been much more visible. It seemed more appropriate to have different balancing adaptors and augmenting adaptors that would replicate the interface to do that work.

What are the consequences of your choices, for users and implementors?

As focus was put on versatility and comprehensiveness, we hope users will find this a powerful framework that covers most important aspects of dealing with hierarchical data structures in a rather intuitive way, once they have adapted to the notion of cursors which, although being the interface relevant portion of the well-known node implementation of trees, partly diverge in their usage from plain node objects.

Wherever reasonably possible, strong time complexity guarantees are given, which mostly, while trying not to require much space overhead, demand implementations that make use of any time and space saving techniques available (e.g. using arrays for both children of a binary tree node, see e.g. [austern]), which may partly restrict implementors to one "proper" way of doing things.

What decisions are left up to implementors?

Most of the requirements for the library components presented in this proposal are rather tightly formulated in order to allow for them being both efficient and general enough. It is however hoped that the conceptual abstraction of hierarchies and cursors may be of general use, also allowing for more specific implementations where required (although probably not as part of the library; ideally comparable to the role of containers and iterators in modern C++ code).

If there are any similar libraries in use, how do their design decisions compare to yours?

Trees, having attracted much attention in the C++ community, are found in various implementations and as subjects of a number of papers. Contrary to the present proposal, practically all of them deal either with trees as used for sorted associative containers (with logarithmic time complexity for more relevant operations, achieved by some sort of balancing; examples are [dreizin], [ekman] and [karas]; plus, most current STL implementations use a red-black tree as their associative containers' base) or with what we call "external" hierarchies in the following (whose structure is dictated e.g. by a file system directory tree, an XML file or an AST; see e.g. [gottschlich], [haas], [parent] and [peeters]), but rarely both fields of application.

Approaches as found in [austern] or [mirwaisi] go some steps further and have provided valuable inspiration for this project, but still do not formalize anything similar as the cursor-based interface in this proposal for dealing with a tree's contents.

The BGL, finally, deals with graphs that are even more general than hierarchical ones, which does not allow them to profit from specific hierarchy properties as much as the ones presented in this proposal. Making cursors logical extensions of iterators would probably also have been more difficult with a BGL-based approach.

Future Directions

While it is hoped that the current proposal somewhat reunites balanced binary trees, B-trees and "external" hierarchies, which should also facilitate work with some higher-level structures (e.g. n-ary trees to implement tries), some of those higher-level components might be an interesting feature to add to the library, such as patricia tries or ternary search tries.

Proposed Text for Technical Report 2

Notes that are not part of the proposed text appear in gray boxes.

23 Containers library[tr.containers]

23.X Hierarchy containers [tr.hierarchy]

23.X.1 Hierarchy container requirements [tr.hierarchy.req]

  1. A hierarchy is an object that stores a finite set of objects, all of the same type, in a hierarchical manner. Hierarchies introduce a cursor concept for navigation instead of iterators. The library provides two kinds of native hierarchies: binary_tree, and nary_tree, along with hierarchy-yielding hierarchy adaptors forest_tree, and multiway_tree.

  2. Hierarchy containers conform to the requirements of Containers ([lib.container.requirements]), except that the expressions in Table 1 are not required to be valid, where a and b denote values of a type X, and X is a hierarchy container class:

    Table 1: Container requirements that are not required for hierarchy containers
    unsupported expression
    X::iterator
    X::const_iterator
    X::reverse_iterator
    X::const_reverse_iterator
    a.begin()
    a.end()
    a.rbegin()
    a.rend()
    a < b
    a > b
    a <= b
    a >= b
  3. Non-constant complexity requirements in this clause are stated in one of a number of possible different ways: unless specified otherwise, they are expressed in terms of the number of operations n, which stands for the total number of elements in the hierarchy; in some cases, however, they are stated in terms of another value.

  4. In Table 2: X denotes a hierarchy class containing objects of type T and a denotes a value of type X.

    Table 2 - Hierarchy requirements (in addition to container)
    expression return type assertion/note
    pre/post-condition
    complexity
    X::cursor cursor type pointing to T any cursor category compile time
    X::const_cursor cursor type pointing to const T any cursor category compile time
    a.root() iterator for mutable a;
    const_iterator for constant a
      constant
    a.croot() const_iterator   constant
    a.shoot() iterator for mutable a;
    const_iterator for constant a
      (Note A)
    a.cshoot() const_iterator   (Note A)
    typename X::template
      rebind<U>::other
    Y For all U (including T), Y::template rebind<T>::other is X. compile time

    Notes: Those entries marked "(Note A)" should have at worst linear complexity. See the individual hierarchy containers for specific complexity.

  5. root() and croot() return a cursor which is the on-top value for the hierarchy. shoot() and cshoot() return a cursor which is the past-the-end value that is found one past the hierarchy's rightmost element. If the hierarchy is empty, then root() == shoot();

  6. Copy constructors for all hierarchy types defined in this clause copy the allocator argument from their respective first parameters. All other constructors for these hierarchy types take an Allocator& argument (20.1.5). A copy of this argument is used for any memory allocation performed, by these constructors and by all member functions, during the lifetime of each hierarchy object. In all hierarchy types defined in this clause, the member get_allocator() returns a copy of the Allocator object used to construct the hierarchy.

  7. The member class template rebind in the table above is effectively a typedef template: if the name Hierarchy is bound to SomeHierarchy<T>, then Hierarchy::rebind<U>::other is the same type as SomeHierarchy<U>. Additionally, because of the related assertion, given SomeHierarchy<T,R0,...,Rn> for all template arguments present is bound to the name Hierarchy, then Hierarchy::rebind<U>::other is the same type as SomeHierarchy<U,S0,...,Sn> such that the types S0 through Sn are the same as R0 through Rn, respectively, when U is the same type as T.

  8. A hierarchy satisfying the requirements shown in Table 3 is called a mutable hierarchy. In Table 3, X denotes a hierarchy class, a denotes a value of X, c denotes a valid, non-on-top cursor satisfying input cursor requirements, p denotes a valid, non-on-top cursor to a, q denotes a valid, dereferenceable cursor to a, and t denotes a value of X::value_type.

    Table 3: Mutable hierarchy requirements
    expression return type assertion/note
    pre/post-condition
    complexity
    a.insert(p,t) cursor inserts a copy of t before p (Note A)
    a.clear(q) void deletes the subtree of q and the element q points to.
    pre: q is dereferenceable.
    Should be at worst linear in the the number of elements in the subtree of q plus the distance to q's parent's end().
    a.clear() void while (a.size()) clear(a.begin());
    post: a.size() == 0
    (Note A)

    Notes: Those entries marked "(Note A)" should have at worst linear complexity. See the individual hierarchy containers for specific complexity.

  9. The cursor returned from a.insert(p,t) points to the copy of t inserted into a. Its parent cursor is the same as that of p.

23.X.2 Plain hierarchies [tr.hierarchy.plain]

  1. A hierarchy is called plain hierarchy if its cursor and const_cursor types satisfy the requirements of a plain cursor.

  2. The library provides one native kind of plain hierarchy, nary_tree, and a hierarchy adaptor that in turn yields a plain hierarchy, forest_tree.

  3. For a mutable plain hierarchy, the following expression as shown in Table 4, is additionally required to be valid:

    Table 4: Plain hierarchy requirements
    expression return type assertion/note
    pre/post-condition
    complexity
    a.insert(p,c) cursor inserts a copy of the subtree of c before p.
    pre: c is dereferenceable.
    Should be at worst linear in the the number of elements in the subtree of c plus the distance to p's parent's end().
    a.insert_above(p,t) cursor inserts a copy of t as child of p's parent and new parent of p and its siblings.
    pre: c is dereferenceable.
    Linear in the the number p's siblings.
  4. The cursor returned from a.insert(p,c) points to the copy of the element that c points to, inserted into a. Its parent cursor is the same as that of p.

23.X.3 Multiway hierarchies [tr.hierarchy.multiway]

  1. A hierarchy is called multiway hierarchy if its cursor and const_cursor types satisfy the requirements of a multiway cursor.

  2. The library provides one native kind of multiway hierarchy, binary_tree, and a hierarchy adaptor that in turn yields a multiway hierarchy, multiway_tree.

  3. For a mutable multiway hierarchy, the semantics of some expressions from Table 3 are modified as shown in Table 5.

    Table 5: Multiway hierarchy requirements
    expression return type assertion/note
    pre/post-condition
    complexity
    a.clear(q) void deletes the subtree of q.
    If q is dereferenceable, the expression also deletes the element q points to.
    If q is past-the-end, the expression deletes the element q's predecessor points to.
    If after either of these steps q has only a non-empty past-the-end child, that child's children become q's children instead. Finally, that child is deleted.
    pre: q is internal.
    Should be at worst linear in the the number of elements in the subtree of c plus the distance to p's parent's end().

23.X.4 Trees [tr.hierarchy.tree]

  1. Headers <binary_tree>, <nary_tree>, <forest_tree>, and <multiway_tree>.

Header <binary_tree> synopsis
namespace std {
namespace tr2 {
  template <class T, class Alloc = std::allocator<T> >
    class binary_tree;

  template <class T, class Alloc>
    bool operator==(  binary_tree<T, Alloc> const& x,
                      binary_tree<T, Alloc> const& y);
  template <class T, class Alloc>
    bool operator!=(  binary_tree<T, Alloc> const& x,
                      binary_tree<T, Alloc> const& y);
  template <class T, class Alloc>
    void swap(  binary_tree<T, Alloc>& x,
                binary_tree<T, Alloc>& y);
  namespace inorder {
  template <class Tp, class Alloc>
    inorder::iterator<binary_tree<Tp, Alloc>::cursor>
      begin(binary_tree<Tp, Alloc>& h);
  template <class Tp, class Alloc>
    inorder::iterator<binary_tree<Tp, Alloc>::const_cursor>
      cbegin(binary_tree<Tp, Alloc> const& h);
  } // namespace inorder

} // namespace tr2
} // namespace std
Header <nary_tree> synopsis
namespace std {
namespace tr2 {
  template <class T, class Alloc = std::allocator<T> >
    class nary_tree;

  template <class T, class Alloc>
    bool operator==(  binary_tree<T, Alloc> const& x,
                      binary_tree<T, Alloc> const& y);
  template <class T, class Alloc>
    bool operator!=(  binary_tree<T, Alloc> const& x,
                      binary_tree<T, Alloc> const& y);
  template <class T, class Alloc>
  void swap(  nary_tree<T, Alloc>& x,
              nary_tree<T, Alloc>& y);
  namespace inorder {
  template <class T, class Alloc>
    inorder::iterator<binary_tree<T, Alloc>::cursor>
      begin(binary_tree<T, Alloc>& h);
  template <class T, class Alloc>
    inorder::iterator<binary_tree<T, Alloc>::const_cursor>
      cbegin(binary_tree<T, Alloc> const& h);
  } // namespace inorder
} // namespace tr2
} // namespace std
Header <forest_tree> synopsis
namespace std {
namespace tr2 {
  template <class T, class Hierarchy = binary_tree<T> >
    class forest_tree;

  template <class T, class Hierarchy>
    bool operator==(  forest_tree<T, Hierarchy> const& x,
                      forest_tree<T, Hierarchy> const& y);
  template <class T, class Alloc>
    bool operator!=(  forest_tree<T, Hierarchy> const& x,
                      forest_tree<T, Hierarchy> const& y);
  template <class T, class Hierarchy>
  void swap(  forest_tree<T, Hierarchy>& x,
              forest_tree<T, Hierarchy>& y);
  namespace inorder {
  template <class T, class Hierarchy>
    inorder::iterator<forest_tree<T, Hierarchy>::cursor>
      begin(forest_tree<T, Hierarchy>& h);
  template <class T, class Alloc>
    inorder::iterator<forest_tree<T, Hierarchy>::const_cursor>
      cbegin(forest_tree<T, Hierarchy> const& h);
  } // namespace inorder
} // namespace tr2
} // namespace std
Header <multiway_tree> synopsis
namespace std {
namespace tr2 {
  template <class T, class Hierarchy = nary_tree< std::vector<T> > >
    class multiway_tree;

  template <class T, class Hierarchy>
    bool operator==(  multiway_tree<T, Hierarchy> const& x,
                      multiway_tree<T, Hierarchy> const& y);
  template <class T, class Alloc>
    bool operator!=(  multiway_tree<T, Hierarchy> const& x,
                      multiway_tree<T, Hierarchy> const& y);
  template <class T, class Hierarchy>
    void swap(  multiway_tree<T, Hierarchy>& x,
                multiway_tree<T, Hierarchy>& y);
  namespace inorder {
  template <class T, class Hierarchy>
    inorder::iterator<multiway_tree<T, Hierarchy>::cursor>
      begin(multiway_tree<T, Hierarchy>& h);
  template <class T, class Alloc>
    inorder::iterator<multiway_tree<T, Hierarchy>::const_cursor>
      cbegin(multiway_tree<T, Hierarchy> const& h);
  } // namespace inorder
} // namespace tr2
} // namespace std
23.X.4.1 Template class binary_tree [tr.hierarchy.bintree]
  1. A binary_tree is a kind of hierarchy that satisfies multiway hierarchy requirements. Additionally, it supports (inorder-invariant) cursor rotation. Descriptions are provided here only for operations on binary_tree that are not described in one of these tables or for operations where there is additional semantic information.

    namespace std {
    namespace tr2 {
      template <class T, class Alloc = std::allocator<T> >
      class binary_tree
      {
      public:
        // types:
        typedef T                                             value_type;
        typedef Alloc                                         allocator_type;
    
        typedef implementation defined                        cursor;
        typedef implementation defined                        const_cursor;
    
        typedef typename allocator_type::pointer              pointer;
        typedef typename allocator_type::const_pointer        const_pointer;
        typedef typename allocator_type::reference            reference;
        typedef typename allocator_type::const_reference      const_reference;
        typedef typename allocator_type::size_type            size_type;
        typedef typename allocator_type::difference_type      difference_type;
    
        template <class U> struct rebind {
          typedef binary_tree< U, typename allocator_type::template rebind<U>::other >
            other;
        };
    
        // construct/copy/destroy:
        explicit binary_tree (allocator_type const& = allocator_type());
        template <class InputCursor>
          binary_tree (InputCursor subtree,
            allocator_type const& = allocator_type());
        binary_tree (binary_tree<T, Alloc> const& x);
        ~binary_tree();
        binary_tree<T, Alloc>& operator=(
          binary_tree<T, Alloc> const& x);
        template <class InputCursor>
          void assign(InputCursor subtree);
        allocator_type get_allocator() const;
    
        // cursors:
        cursor        root();
        const_cursor  croot() const;
        cursor        shoot();
        const_cursor  cshoot() const;
        cursor        inorder_first();
        const_cursor  inorder_cfirst const();
    
        // capacity:
        bool      empty() const;
        size_type size() const;
        size_type max_size() const;
    
        // modifiers:
        cursor    insert(cursor position, value_type const& x = value_type());
        template <class InputCursor>
          cursor  insert(cursor position, InputCursor subtree);
        void      rotate(cursor position);
        void      swap(binary_tree<T, Alloc>&);
        void      clear(cursor position);
        void      clear();
      };
    
      template <class T, class Alloc>
        bool operator==(  binary_tree<T, Alloc> const& x,
                          binary_tree<T, Alloc> const& y);
      template <class T, class Alloc>
        bool operator!=(  binary_tree<T, Alloc> const& x,
                          binary_tree<T, Alloc> const& y);
    
      // specialized algorithms:
      template <class T, class Alloc>
        void swap(  binary_tree<T, Alloc>& x,
                    binary_tree<T, Alloc>& y);
                  
      namespace inorder {
      template <class T, class Alloc>
        inorder::iterator<binary_tree<T, Alloc>::cursor>
          begin(binary_tree<T, Alloc>& h);
      template <class T, class Alloc>
        inorder::iterator<binary_tree<T, Alloc>::const_cursor>
          cbegin(binary_tree<T, Alloc> const& h);
      } // namespace inorder
      
    } // namespace tr2
    } // namespace std
    
23.X.4.1.1 binary_tree types [tr.hierarchy.bintree.types]
typedef implementation defined                        cursor;
typedef implementation defined                        const_cursor;    
  1. Both cursor and const_cursor have to fulfill the multiway cursor ([tr.cursor.flavors]) and ascending random access cursor ([tr.ascending.random.access.cursors]) requirements.

  2. Additionally, for any instance a of either type cursor or const_cursor, a.max_size() == 1.

23.X.4.1.2 binary_tree constructors, copy, and assignment [tr.hierarchy.bintree.cons]
    explicit binary_tree (allocator_type const& = allocator_type());
    template <class InputCursor>
      binary_tree (InputCursor subtree,
        allocator_type const& = allocator_type());
    binary_tree (binary_tree<T, Alloc> const& x);
  1. Complexity: The constructor template <class InputCursor> vector(InputCursor subtree) makes only N calls to the copy constructor of T (where N is the number of elements in subtree) and no reallocations if the cursor subtree is of (either descending or ascending) forward, bidirectional, or random access categories. It does at most 2N calls to the copy constructor of T and logN reallocations if they are just cursors, since it is impossible to determine the size of subtree and then do copying.

        template <class InputCursor>
          void assign(InputCursor subtree);
    
  2. Effects:

    clear(); 
    for(InputCursor i = subtree.begin(); i != subtree.end(); ++i)
      insert(root.end(), *i);
    
23.X.4.1.3 binary_tree cursors [tr.hierarchy.bintree.cursors]
    cursor        shoot();
    const_cursor  cshoot() const;
  1. Complexity: constant

        cursor        inorder_first();
        const_cursor  inorder_cfirst() const;
    
  2. Returns: A cursor to the binary_tree's first element in inorder (see [tr.order.iterators], §4).

  3. Complexity: constant.

23.X.4.1.4 binary_tree modifiers [tr.hierarchy.bintree.modifiers]
    cursor    insert(cursor position, value_type const& x = value_type());
  1. Notes: Does not affect the validity of cursors and references.

  2. Effects: Let b be a's parent;
    if b.size() < b.max_size(), insert a copy of t before p, as child of b;
    Otherwise, if a.empty(), insert a copy of t as child of a; and if !a.empty(), insert a copy of t as parent of a's current child, as new child of a.

  3. Complexity: constant

        template <class InputCursor>
          cursor  insert(cursor position, InputCursor subtree);
    
  4. Notes: Does not affect the validity of cursors and references.

  5. Effects: as above, substituting InputCursor subtree to insert instead of value_type const& x.

  6. Complexity: linear in the number of elements in subtree.

        void      rotate(cursor position);
    
  7. Precondition: position and its parent are internal and non-on-top

  8. Effects: Performs a left tree rotation around the parent of position if position.parity() == 0 or a right tree rotation if position.parity() == 1.

  9. Postcondition: If par == position.parity() as of before the rotation, then, after the rotation:

    • *position.begin() yields the same value it yielded before the rotation
    • position.parity() == !par
    • *(((position.begin())[par]).begin()) yields what *(p.begin()) yielded before, if p was position's parent
    • position's parent's value is what position's parent's parent's value yielded before. The ancestors of that cursor, and their structure, remain unchanged
    • (position.begin())[!par]'s subtree is what (position.begin())[!par]'s was before.
    • ((position.begin()[!par]).begin())[!par]'s subtree is what (p.begin())[!par]'s was before, if p was position's parent.
    • ((position.begin()[!par]).begin())[par]'s subtree is what (position.begin())[!par]'s was before.
  10. Complexity: constant

  11. Notes: Does not affect the validity of cursors and references. Tree rotations are important inorder-preserving (see [tr.order.iterators] §4) operations on binary trees that are especially required by balancers.

        void      clear(cursor position);
    
  12. Notes: Invalidates only the cursors and references to the erased elements.

23.X.4.1.5 binary_tree specialized algorithms [tr.hierarchy.bintree.special]
    template <class T, class Alloc>
      void swap(  binary_tree<T, Alloc>& x,
                  binary_tree<T, Alloc>& y);
  1. Effects: x.swap(y);

        namespace inorder {
          template <class T, class Alloc>
            inorder::iterator<binary_tree<T, Alloc>::cursor>
              begin(binary_tree<T, Alloc>& h);
        } // namespace inorder
    
  2. Returns: inorder::iterator<binary_tree<T, Alloc>::cursor>(h.inorder_first()).

  3. Complexity: constant

        namespace inorder {
          template <class T, class Alloc>
            inorder::iterator<binary_tree<T, Alloc>::const_cursor>
              cbegin(binary_tree<T, Alloc> const& h);
        } // namespace inorder
    
  4. Returns: inorder::iterator<binary_tree<T, Alloc>::const_cursor>(h.inorder_cfirst()).

  5. Complexity: constant

23.X.4.2 Template class nary_tree [tr.hierarchy.narytree]
namespace std {
namespace tr2 {
  template <class T, class Alloc = std::allocator<T> >
  class nary_tree {
  public:
    // types:
    typedef T                                             value_type;
    typedef Alloc                                         allocator_type;

    typedef implementation defined                        cursor;
    typedef implementation defined                        const_cursor;

    typedef typename allocator_type::pointer              pointer;
    typedef typename allocator_type::const_pointer        const_pointer;
    typedef typename allocator_type::reference            reference;
    typedef typename allocator_type::const_reference      const_reference;
    typedef typename allocator_type::size_type            size_type;
    typedef typename allocator_type::difference_type      difference_type;

    template <class U> struct rebind {
      typedef nary_tree< U, typename allocator_type::template rebind<U>::other >
        other;
    };

    // construct/copy/destroy:
    explicit nary_tree (allocator_type const& = allocator_type());
    template <class InputCursor>
      nary_tree (InputCursor subtree,
        allocator_type const& = allocator_type());
    nary_tree (nary_tree<T, Alloc> const& x);
    ~nary_tree();
    nary_tree<T, Alloc>& operator=(
      nary_tree<T, Alloc> const& x);
    template <class InputCursor>
      void assign(InputCursor subtree);
    allocator_type get_allocator() const;

    // cursors:
    cursor        root();
    const_cursor  croot() const;
    cursor        shoot();
    const_cursor  cshoot() const;
    cursor        inorder_first();
    const_cursor  inorder_cfirst const();

    // capacity:
    bool      empty() const;
    size_type size() const;
    size_type max_size() const;
    size_type capacity(cursor position) const;
    void      reserve(cursor position, size_type n);

    // modifiers:
    cursor    insert(cursor position, value_type const& x = value_type());
    template <class InputCursor>
      cursor  insert(cursor position, InputCursor subtree);
    cursor    insert_above(cursor position, value_type const& x = value_type());
    void      swap(nary_tree<Tp, Alloc>&);
    void      clear(cursor position);
    void      clear();
  };

  template <class T, class Alloc>
    bool operator==(  nary_tree<T, Alloc> const& x,
                      nary_tree<T, Alloc> const& y);
  template <class T, class Alloc>
    bool operator!=(  nary_tree<T, Alloc> const& x,
                      nary_tree<T, Alloc> const& y);

  // specialized algorithms:
  template <class T, class Alloc>
    void swap(  nary_tree<T, Alloc>& x,
                nary_tree<T, Alloc>& y);

  namespace inorder {
  template <class T, class Alloc>
    inorder::iterator<nary_tree<T, Alloc>::cursor>
      begin(nary_tree<T, Alloc>& h);
  template <class T, class Alloc>
    inorder::iterator<nary_tree<T, Alloc>::const_cursor>
      cbegin(nary_tree<T, Alloc> const& h);
  } // namespace inorder
              
} // namespace tr2
} // namespace std
23.X.4.2.1 nary_tree types [tr.hierarchy.narytree.types]
typedef implementation defined                        cursor;
typedef implementation defined                        const_cursor;    
  1. Both cursor and const_cursor have to fulfill the plain cursor ([tr.cursor.flavors]) and ascending random access cursor ([tr.ascending.random.access.cursors]) requirements.

23.X.4.2.2 nary_tree constructors, copy, and assignment [tr.hierarchy.narytree.cons]
    explicit nary_tree (allocator_type const& = allocator_type());
    template <class InputCursor>
      nary_tree (InputCursor subtree,
        allocator_type const& = allocator_type());
    nary_tree (nary_tree<T, Alloc> const& x);
  1. Complexity: The constructor template <class InputCursor> vector(InputCursor subtree) makes only N calls to the copy constructor of T (where N is the number of elements in subtree) and no reallocations if the cursor subtree is of (either descending or ascending) forward, bidirectional, or random access categories. It does at most 2N calls to the copy constructor of T and logN reallocations if they are just cursors, since it is impossible to determine the size of subtree and then do copying.

        template <class InputCursor>
          void assign(InputCursor subtree);
    
  2. Effects:

    clear();
    for(InputCursor i = subtree.begin(); i != subtree.end(); ++i)
      insert(root.end(), *i);
    
23.X.4.2.3 nary_tree cursors [tr.hierarchy.narytree.cursors]
    cursor        shoot();
    const_cursor  cshoot() const;
  1. Complexity: constant

        cursor        inorder_first();
        const_cursor  inorder_cfirst() const;
    
  2. Returns: A cursor to the nary_tree's first element in inorder (see [tr.order.iterators], §4).

  3. Complexity: constant.

23.X.4.2.4 nary_tree capacity [tr.hierarchy.narytree.capacity]
size_type capacity(cursor position) const;
  1. Returns: The total number of child elements that the cursor position can hold without requiring reallocation.

    void      reserve(cursor position, size_type n);
    
  2. Effects: A directive that informs an nary_tree of a planned change in a given cursor's size, so that it can manage the storage allocation accordingly. After reserve(position, n), capacity(position) is greater or equal to the size_type argument n of reserve if reallocation happens; and equal to the previous value of capacity(position) otherwise. Reallocation happens at this point if and only if the current capacity is less than the size_type argument n of reserve().

  3. Complexity: It does not change the size of the nary_tree and takes at most linear time in position.size().

  4. Notes: Reallocation invalidates all the references, pointers, and cursors referring to the child elements of position. It is guaranteed that no reallocation takes place during insertions to position that happen after a call to reserve() until the time when an insertion would make position.size() greater than the size specified in the most recent call to reserve().

23.X.4.2.5 nary_tree modifiers [tr.hierarchy.narytree.modifiers]
    cursor    insert(cursor position, value_type const& x = value_type());
    template <class InputCursor>
      cursor  insert(cursor position, InputCursor subtree);
    cursor    insert_above(cursor position, value_type const& x = value_type());
  1. Notes: Does not affect the validity of cursors and references.

        void      clear(cursor position);  
    
  2. Notes: Invalidates only the cursors and references to the erased elements.

23.X.4.2.6 nary_tree specialized algorithms [tr.hierarchy.narytree.special]
    template <class T, class Alloc>
    void swap(  nary_tree<T, Alloc>& x,
                nary_tree<T, Alloc>& y);
  1. Effects: x.swap(y);

        namespace inorder {
          template <class T, class Alloc>
            inorder::iterator<nary_tree<T, Alloc>::cursor>
              begin(nary_tree<T, Alloc>& h);
        } // namespace inorder
    
  2. Returns: inorder::iterator<nary_tree<T, Alloc>::cursor>(h.inorder_first()).

  3. Complexity: constant

        namespace inorder {
          template <class T, class Alloc>
            inorder::iterator<nary_tree<T, Alloc>::const_cursor>
              cbegin(nary_tree<T, Alloc> const& h);
        } // namespace inorder
    
  4. Returns: inorder::iterator<nary_tree<T, Alloc>::const_cursor>(h.inorder_cfirst()).

  5. Complexity: constant

23.X.4.3 Hierarchy adaptors [tr.hierarchy.adaptors]

  1. Hierarchy adaptors each take a Hierarchy template parameter, and each of their constructors takes a Hierarchy reference argument. This hierarchy is copied into the Hierarchy member of each adapter. Most hierarchy adaptors satisfy most of the hierarchy requirements (except for anything that deals with allocators, as storage management is done by the adaptees). The exception is the group of balancing hierarchy adaptors ([tr.hierarchy.balance]), whose members satisfy most of the requirements of a container, of a sequence and most of the optional sequence requirements instead (again except for anything allocation related, and some other exceptions).

23.X.4.3.1 Template class forest_tree [tr.hierarchy.foresttree]
  1. A forest_tree is a kind of mutable plain hierarchy that is instantiated with a mutable multiway hierarchy that has insertion semantics as a binary_tree ([tr.hierarchy.bintree.modifiers], §1)), and whose cursor types cursor and const_cursor satisfy a binary_tree's cursor and const_cursor type requirements ([tr.hierarchy.bintree.types], §1-2)).

    namespace std {
    namespace tr2 {
      template <class T, class Hierarchy = binary_tree<T> >
      class forest_tree {
      public:
        typedef Hierarchy                                     hierarchy_type;
    
      protected:
        hierarchy_type h;
        
      public:
        // types:
        typedef T                                             value_type;
    
        typedef implementation defined                        cursor;
        typedef implementation defined                        const_cursor;
    
        typedef typename hierarchy_type::pointer              pointer;
        typedef typename hierarchy_type::const_pointer        const_pointer;
        typedef typename hierarchy_type::reference            reference;
        typedef typename hierarchy_type::const_reference      const_reference;
        typedef typename hierarchy_type::size_type            size_type;
        typedef typename hierarchy_type::difference_type      difference_type;
    
        template <class U> struct rebind {
          typedef forest_tree< U, typename hierarchy_type::template rebind<U>::other >
            other;
        };
    
        // construct/copy/destroy:
        explicit forest_tree (hierarchy_type const& = hierarchy_type());
        template <class InputCursor>
          forest_tree (InputCursor subtree);
        forest_tree (forest_tree<T, Hierarchy> const& x);
        forest_tree<T, Hierarchy>& operator=(
          forest_tree<T, Hierarchy> const& x);
        template <class InputCursor>
          void assign(InputCursor subtree);
    
        // cursors:
        cursor        root()    { return h.root(); }
        const_cursor  croot()   { return h.croot(); }
        cursor        shoot();
        const_cursor  cshoot() const;
    
        // capacity:
        bool      empty() const { return h.empty(); }
        size_type size() const  { return h.size(); }
        size_type max_size() const;
    
        // modifiers:
        cursor    insert(cursor position, value_type const& x = value_type());
        template <class InputCursor>
          cursor  insert(cursor position, InputCursor subtree);
        cursor    insert_above(cursor position, value_type const& x = value_type());
        void      swap(forest_tree<Tp, Hierarchy>&);
        void      clear(cursor position);
        void      clear();
      };
    
      template <class T, class Hierarchy>
        bool operator==(  forest_tree<T, Hierarchy> const& x,
                          forest_tree<T, Hierarchy> const& y);
      template <class T, class Hierarchy>
        bool operator!=(  forest_tree<T, Hierarchy> const& x,
                          forest_tree<T, Hierarchy> const& y);
    
      // specialized algorithms:
      template <class T, class Hierarchy>
        void swap(  forest_tree<T, Hierarchy>& x,
                    forest_tree<T, Hierarchy>& y);
    
      namespace inorder {
      template <class T, class Hierarchy>
        inorder::iterator<forest_tree<T, Hierarchy>::cursor>
          begin(forest_tree<T, Hierarchy>& h);
      template <class T, class Hierarchy>
        inorder::iterator<forest_tree<T, Hierarchy>::const_cursor>
          cbegin(forest_tree<T, Hierarchy> const& h);
      } // namespace inorder
    
    } // namespace tr2
    } // namespace std
    
23.X.4.3.1.1 forest_tree types [tr.hierarchy.foresttree.types]
typedef implementation defined                        cursor;
typedef implementation defined                        const_cursor;    
  1. Notes: If (the adaptee) Hierarchy's cursor types are at least ascending bidirectional cursors, both cursor and const_cursor are ascending bidirectional cursors. Otherwise, they are descending forward cursors. The adaptee binary tree is "tilted" to yield an n-ary tree, meaning that the operational semantics of the adaptor cursor are as follows in terms of the adaptee cursor (only valid if present in the adaptor cursor's category; only given for mutable versions of expressions, const ones as according; expressions missing from the list mean operational semantics and complexity are for b as they are for f):

    Table 6: forest_tree/binary tree cursor operational semantics correspondences
    adaptor cursor f adaptee cursor b complexity
    f = f.end() while (!b.empty()) b = b.end(); linear
    ++f b = (++b).begin(); constant
    --f b = --b.parent(); as b.parent()
    !f while ((!b).parity() == 1); b = (!b).begin();
    linear
23.X.4.3.1.2 forest_tree constructors, copy, and assignment [tr.hierarchy.foresttree.cons]
    explicit forest_tree (hierarchy_type const& = hierarchy_type());
    template <class InputCursor>
      forest_tree (InputCursor subtree);
    forest_tree (forest_tree<T, Hierarchy> const&);
  1. Complexity: The constructor template <class InputCursor> vector(InputCursor subtree) makes only N calls to the copy constructor of T (where N is the number of elements in subtree) and no reallocations if the cursor subtree is of (either descending or ascending) forward, bidirectional, or random access categories. It does at most 2N calls to the copy constructor of T and logN reallocations if they are just cursors, since it is impossible to determine the size of subtree and then do copying.

        template <class InputCursor>
          void assign(InputCursor subtree);
    
  2. Effects:

    clear();
    for(InputCursor i = subtree.begin(); i != subtree.end(); ++i)
      insert(root.end(), *i);
    
23.X.4.3.1.3 forest_tree modifiers [tr.hierarchy.foresttree.modifiers]
    cursor    insert(cursor position, value_type const& x = value_type());
    template <class InputCursor>
      cursor  insert(cursor position, InputCursor subtree);
    cursor    insert_above(cursor position, value_type const& x = value_type());
  1. Notes: Does not affect the validity of cursors and references.

        void      clear(cursor position);  
    
  2. Notes: Invalidates only the cursors and references to the erased elements.

23.X.4.3.1.4 forest_tree specialized algorithms [tr.hierarchy.foresttree.special]
    template <class T, class Hierarchy>
    void swap(  forest_tree<T, Hierarchy>& x,
                forest_tree<T, Hierarchy>& y);
  1. Effects: x.swap(y);

23.X.4.3.2 Template class multiway_tree [tr.hierarchy.multiwaytree]
  1. A multiway_tree is a kind of mutable multiway hierarchy that is instantiated with a mutable plain hierarchy whose value type in turn is a container holding elements of multiway_tree's value_type.

    namespace std {
    namespace tr2 {
      template <class T, class Hierarchy = nary_tree< std::vector<T> > >
      class multiway_tree
      {
      public:
        typedef Hierarchy                                     hierarchy_type;
    
      protected:
        hierarchy_type h;
    
      public:
        // types:
        typedef T                                             value_type;
    
        typedef implementation defined                        cursor;
        typedef implementation defined                        const_cursor;
    
        typedef typename hierarchy_type::pointer              pointer;
        typedef typename hierarchy_type::const_pointer        const_pointer;
        typedef typename hierarchy_type::reference            reference;
        typedef typename hierarchy_type::const_reference      const_reference;
        typedef typename hierarchy_type::size_type            size_type;
        typedef typename hierarchy_type::difference_type      difference_type;
    
        template <class U> struct rebind {
          typedef multiway_tree< U,
            typename hierarchy_type::template rebind< implementation defined >::other >
              other;
        };
    
        // construct/copy/destroy:
        explicit multiway_tree (hierarchy_type const& = hierarchy_type());
        template <class InputCursor>
          multiway_tree (InputCursor subtree);
        multiway_tree (multiway_tree<T, Hierarchy> const& x);
        ~multiway_tree();
        multiway_tree<T, Hierarchy>& operator=(
          multiway_tree<T, Hierarchy> const& x);
        template <class InputCursor>
          void assign(InputCursor subtree);
    
        // cursors:
        cursor        root();
        const_cursor  croot() const;
        cursor        shoot();
        const_cursor  cshoot() const;
        cursor        inorder_first();
        const_cursor  inorder_cfirst const();
    
        // capacity:
        bool      empty() const;
        size_type size() const;
        size_type max_size() const;
        size_type capacity(cursor position) const;
        void      reserve(cursor position, size_type n);
    
        // modifiers:
        cursor    insert(cursor position, value_type const& x = value_type());
        template <class InputCursor>
          cursor  insert(cursor position, InputCursor subtree);
        void      rotate(cursor position);
        void      swap(multiway_tree<p, Hierarchy>&);
        void      clear(cursor position);
        void      clear();
      };
    
      template <class T, class Hierarchy>
        bool operator==(  multiway_tree<T, Hierarchy> const& x,
                          multiway_tree<T, Hierarchy> const& y);
      template <class Tp, class Alloc>
        bool operator!=(  multiway_tree<T, Hierarchy> const& x,
                          multiway_tree<T, Hierarchy> const& y);
    
      // specialized algorithms:
      template <class T, class Hierarchy>
        void swap(  multiway_tree<T, Hierarchy>& x,
                    multiway_tree<T, Hierarchy>& y);
    
      namespace inorder {
      template <class T, class Hierarchy>
        inorder::iterator<multiway_tree<T, Hierarchy>::cursor>
          begin(multiway_tree<T, Hierarchy>& h);
      template <class T, class Hierarchy>
        inorder::iterator<multiway_tree<T, Hierarchy>::const_cursor>
          cbegin(multiway_tree<T, Hierarchy> const& h);
      } // namespace inorder
      
    } // namespace tr2
    } // namespace std
    
  2. Types typename Hierarchy::cursor and typename Hierarchy::const_cursor are required to be random access cursors.

23.X.4.3.2.1 multiway_tree types [tr.hierarchy.multiwaytree.types]
    typedef implementation defined                        cursor;
    typedef implementation defined                        const_cursor;
  1. Both cursor and const_cursor have to fulfill the plain cursor requirements ([tr.cursor.flavors]). If typename hierarchy_type::cursor is an ascending random access cursor, cursor and const_cursor are also ascending random access cursors ([tr.ascending.random.access.cursors]); otherwise, they are descending random access cursor ([tr.descending.random.access.cursors]).

  2. Notes: The operational semantics of the adaptor cursor are as follows in terms of the adaptee cursor (only valid if present in the adaptor cursor's category; only given for mutable versions of expressions, const ones as according; expressions missing from the list mean operational semantics and complexity are for m as they are for n):

    Table 7: Multiway/nary tree cursor operational semantics correspondences
    adaptor cursor m adaptee cursor n complexity
    *m *((p->begin())[b.parity()]) constant
23.X.4.3.2.2 multiway_tree constructors, copy, and assignment [tr.hierarchy.multiwaytree.cons]
    explicit multiway_tree (hierarchy_type const& = hierarchy_type());
    template <class InputCursor>
      multiway_tree (InputCursor subtree);
    multiway_tree (multiway_tree<T, Hierarchy> const& x);
  1. Complexity: The constructor template <class InputCursor> vector(InputCursor subtree) makes only N calls to the copy constructor of T (where N is the number of elements in subtree) and no reallocations if the cursor subtree is of (either descending or ascending) forward, bidirectional, or random access categories. It does at most 2N calls to the copy constructor of T and logN reallocations if they are just cursors, since it is impossible to determine the size of subtree and then do copying.

        template <class InputCursor>
          void assign(InputCursor subtree);
    
  2. Effects:

    clear();
    for(InputCursor i = subtree.begin(); i != subtree.end(); ++i)
      insert(root.end(), *i);
    
23.X.4.3.2.3 multiway_tree cursors [tr.hierarchy.multiwaytree.cursors]
    cursor        shoot();
    const_cursor  cshoot() const;
  1. Complexity: constant

        cursor        inorder_first();
        const_cursor  inorder_cfirst() const;
    
  2. Returns: A cursor to the multiway_tree's first element in inorder (see [tr.order.iterators], §4).

  3. Complexity: constant.

23.X.4.3.2.4 multiway_tree capacity [tr.hierarchy.multiwaytree.capacity]
size_type capacity(cursor position) const;
  1. Returns: The total number of child elements that the cursor position can hold without requiring reallocation.

    void      reserve(cursor position, size_type n);
    
  2. Effects: A directive that informs an multiway_tree of a planned change in a given cursor's size, so that it can manage the storage allocation accordingly. After reserve(position, n), capacity(position) is greater or equal to the size_type argument n of reserve if reallocation happens; and equal to the previous value of capacity(position) otherwise. Reallocation happens at this point if and only if the current capacity is less than the size_type argument n of reserve().

  3. Complexity: It does not change the size of the multiway_tree and takes at most linear time in position.size().

  4. Notes: Reallocation invalidates all the references, pointers, and cursors referring to the child elements of position. It is guaranteed that no reallocation takes place during insertions to position that happen after a call to reserve() until the time when an insertion would make position.size() greater than the size specified in the most recent call to reserve().

23.X.4.3.2.5 multiway_tree modifiers [tr.hierarchy.multiwaytree.modifiers]
    cursor    insert(cursor position, value_type const& x = value_type());
    template <class InputCursor>
      cursor  insert(cursor position, InputCursor subtree);
    cursor    insert_above(cursor position, value_type const& x = value_type());
  1. Notes: Does not affect the validity of cursors and references.

        void      clear(cursor position);  
    
  2. Notes: Invalidates only the cursors and references to the erased elements.

23.X.4.3.2.6 multiway_tree specialized algorithms [tr.hierarchy.multiwaytree.special]
    template <class T, class Hierarchy>
      void swap(  multiway_tree<T, Hierarchy>& x,
                  multiway_tree<T, Hierarchy>& y);
  1. Effects: x.swap(y);

        namespace inorder {
          template <class T, class Hierarchy>
            inorder::iterator<multiway_tree<T, Hierarchy>::cursor>
              begin(multiway_tree<T, Hierarchy>& h);
        } // namespace inorder
    
  2. Returns: inorder::iterator<multiway_tree<T, Hierarchy>::cursor>(h.inorder_first()).

  3. Complexity: constant

        namespace inorder {
          template <class Tp, class Alloc>
            inorder::iterator<multiway_tree<Tp, Alloc>::const_cursor>
              cbegin(multiway_tree<Tp, Alloc> const& h);
        } // namespace inorder
    
  4. Returns: inorder::iterator<multiway_tree<Tp, Alloc>::const_cursor>(h.inorder_cfirst()).

  5. Complexity: constant

23.X.4.3.3 Augmenting hierarchy adaptors [tr.hierarchy.augment]
  1. An augmenting hierarchy "augments" a mutable multiway hierarchy which it is given as a template parameter by associating additional information with its elements and modeling a mutable multiway hierarchy in turn. This additional information is not directly exposed, but only readable via certain member functions of the augmentor; it is updated internally in order to adapt to structural or content-wise changes in the hierarchy. The library provides one augmenting hierarchy adaptor template class: rank_tree, found in header <augment>.

23.X.4.3.3.1 Template class rank_tree [tr.hierarchy.ranktree]
namespace std {
namespace tr2 {
  template <class T, class Hierarchy = binary_tree<T> >
  class rank_tree
  {
  public:
    typedef Hierarchy                                     hierarchy_type;

  protected:
    typename hierarchy_type::template rebind< pair<T,size_t> >::other h;
  
  public:
    // types:
    typedef T                                             value_type;

    typedef implementation defined                        cursor;
    typedef implementation defined                        const_cursor;

    typedef typename hierarchy_type::pointer              pointer;
    typedef typename hierarchy_type::const_pointer        const_pointer;
    typedef typename hierarchy_type::reference            reference;
    typedef typename hierarchy_type::const_reference      const_reference;
    typedef typename hierarchy_type::size_type            size_type;
    typedef typename hierarchy_type::difference_type      difference_type;

    template <class U> struct rebind {
      typedef rank_tree< U, typename hierarchy_type::template rebind<U>::other >
        other;
    };

    // construct/copy/destroy:
    explicit rank_tree (hierarchy_type const& = hierarchy_type());
    template <class InputCursor>
      rank_tree (InputCursor subtree);
    rank_tree (rank_tree<T, Hierarchy> const& x);
    ~rank_tree();
    rank_tree<T, Hierarchy>& operator=(
      rank_tree<T, Hierarchy> const& x);
    template <class InputCursor>
      void assign(InputCursor subtree);

    // cursors:
    cursor        root();
    const_cursor  croot() const;
    cursor        shoot();
    const_cursor  cshoot() const;
    cursor        inorder_first();
    const_cursor  inorder_cfirst const();

    cursor        rank(size_type n);
    const_cursor  rank(size_type n) const;

    // capacity:
    bool      empty() const;
    size_type size() const;
    size_type max_size() const;
    size_type capacity(cursor position) const;
    void      reserve(cursor position, size_type n);

    // modifiers:
    cursor    insert(cursor position, value_type const& x = value_type());
    template <class InputCursor>
      cursor  insert(cursor position, InputCursor subtree);
    void      rotate(cursor position);
    void      swap(rank_tree<T, Hierarchy>&);
    void      clear(cursor position);
    void      clear();
  };

  template <class T, class Hierarchy>
    bool operator==(  rank_tree<T, Hierarchy> const& x,
                      rank_tree<T, Hierarchy> const& y);
  template <class T, class Hier>
    bool operator!=(  rank_tree<T, Hierarchy> const& x,
                      rank_tree<T, Hierarchy> const& y);

  // specialized algorithms:
  template <class T, class Hierarchy>
    void swap(  rank_tree<T, Hierarchy>& x,
                rank_tree<T, Hierarchy>& y);
              
  namespace inorder {
  template <class T, class Hierarchy>
    inorder::iterator<rank_tree<T, Hierarchy>::cursor>
      begin(rank_tree<T, Hierarchy>& h);
  template <class Tp, class Hierarchy>
    inorder::iterator<rank_tree<T, Hierarchy>::const_cursor>
      cbegin(rank_tree<T, Hierarchy> const& h);
  } // namespace inorder
  
} // namespace tr2
} // namespace std
  1. Each function listed in the public interface of rank_tree as above calls a function of the same name for its adaptee object h, plus possibly other operations with guaranteed logarithmic time complexity in total. This means that operational semantics and time complexities are as specified by the hierarchy_type; and that a function can only be called if a function of the same name is present in the public interface of hierarchy_type. (The only exception to the above stated are the functions rank(), which are newly introduced.)

        cursor        rank(size_type n);
        const_cursor  rank(size_type n) const;
    
  2. Returns: A cursor (or const_cursor) to the nth element of the hierarchy in inorder, counting from inorder_first().

  3. Complexity: logarithmic in size().

23.X.4.3.4 Balancing hierarchy adaptors [tr.hierarchy.balance]
These do not model AssociativeContainer yet but Sequence as they permit insertion in arbitrary positions. (This way, they are not required to take care of extracting, sorting and searching.)
  1. A balancing hierarchy adaptor uses some kind of balancing method in order to guarantee logarithmic time complexity for many important operations while keeping the inorder of the adaptee hierarchy as its invariant.

  2. A balancing hierarchy adaptor satisfies all of the requirements of a container ([lib.container.requirements]), of a sequence ([lib.sequence.reqmts]), with the exception that its erase() member functions return void, and most of the optional sequence requirements, except for the operator[] and at member functions, which are not provided. If the adaptee hierarchy supports at least descending bidirectional cursors, it also satisfies the requirements of a reversible container. Descriptions are provided here only for operations on balancing hierarchy adaptors that are not described in one of these tables or for operations where there is additional semantic information.

  3. The library provides four balancing hierarchy adaptor template classes which take a mutable multiway template parameter that provides a rotate() operation and whose cursor and const_cursor types satisfy the requirements of a binary tree cursor ([tr.hierarchy.bintree.types], §1 and §2): avl_tree, red_black_tree, splay_tree, and treap. Furthermore, two balancing hierarchy adaptor template classes that take a mutable multiway tree template parameter are provided: b_tree and b_star_tree. All balancing adaptors and corresponding free functions are found in header <balance>.

  4. In the following, only the template class avl_tree and related operators are shown. Note that also red_black_tree, splay_tree, and treap must be present and have identical interfaces (with all occurrences of avl_tree replaced accordingly). The same holds true for b_tree and b_star_tree, as well, except that the standard value for the template parameter reads multiway_tree<T> (instead of binary_tree<T>) in their case.

    namespace std {
    namespace tr2 {
      template <class T, class Hierarchy = binary_tree<T> >
      class avl_tree {
      public:
        typedef Hierarchy                                     hierarchy_type;
    
      protected:
        hierarchy_type h;
        
      public:
        // types:
        typedef typename hierarchy_type::value_type           value_type;
        typedef typename hierarchy_type::pointer              pointer;
        typedef typename hierarchy_type::const_pointer        const_pointer;
        typedef typename hierarchy_type::reference            reference;
        typedef typename hierarchy_type::const_reference      const_reference;
        typedef typename hierarchy_type::size_type            size_type;
        typedef typename hierarchy_type::difference_type      difference_type;
    
        typedef implementation defined                        iterator;
        typedef implementation defined                        const_iterator;
    
        typedef std::reverse_iterator<iterator>               reverse_iterator;
        typedef std::reverse_iterator<const_iterator>         const_reverse_iterator;
    
        // construct/copy/destroy:
        explicit avl_tree(hierarchy_type const& = hierarchy_type());
        explicit avl_tree(size_type n, value_type const& value = value_type(),
          hierarchy_type const& = hierarchy_type());
        template <class InputIterator>
          avl_tree (InputIterator first, InputIterator last,
            hierarchy_type const& = hierarchy_type());
        avl_tree (avl_tree<T, Hierarchy> const& x);
        ~avl_tree();
        avl_tree<T, Hierarchy>& operator=(
          avl_tree<T, Hierarchy> const& x);
        template <class InputIterator>
          void assign(InputIterator first, InputIterator last);
        template <class Size, class T>
          void assign(Size n, T const& t = T());
    
        // iterators:
        iterator                begin();
        const_iterator          cbegin() const;
        iterator                end()             { return iterator(h.shoot()); }
        const_iterator          cend() const      { return const_iterator(h.cshoot()); }
        reverse_iterator        rbegin();
        const_reverse_iterator  crbegin() const;
        reverse_iterator        rend();
        const_reverse_iterator  crend() const;
        
        // capacity:
        bool      empty() const { return h.empty(); }
        size_type size() const  { return h.size(); }
        size_type max_size() const;
        void      resize(size_type sz, T c = T());
    
        // element access:
        reference       front();
        const_reference front() const;
        reference       back();
        const_reference back() const;
        
        // map operations:
        iterator find(const value_type& x);
          const_iterator find(const value_type& x) const;
        template <class Cmp>
          iterator find(const value_type& x, Cmp cmp);
            const_iterator find(const value_type& x) const;
    
        size_type count(const value_type& x) const;
        template <class Cmp>
          size_type count(const value_type& x, Cmp cmp) const;
    
        iterator lower_bound(const value_type& x);
        const_iterator lower_bound(const value_type& x) const;
        template <class Cmp>
          iterator lower_bound(const value_type& x, Cmp cmp);
        template <class Cmp>
          const_iterator lower_bound(const value_type& x, Cmp cmp) const;
    
        iterator upper_bound(const value_type& x);
        const_iterator upper_bound(const value_type& x) const;
        template <class Cmp>
          iterator upper_bound(const value_type& x, Cmp cmp);
        template <class Cmp>
          const_iterator upper_bound(const value_type& x, Cmp cmp) const;
    
        pair<iterator,iterator> equal_range(const value_type& x);
        pair<const_iterator,const_iterator>
          equal_range(const value_type& x) const;
        template <class Cmp>
          pair<iterator,iterator>
            equal_range(const value_type& x, Cmp cmp);
        template <class Cmp>
          pair<const_iterator,const_iterator>
            equal_range(const value_type& x, Cmp cmp) const;
    
        // modifiers:
        void      push_front(value_type const& x);
        void      push_back(value_type const& x);
        iterator  insert(iterator position, value_type const& x = value_type());
        void      insert(iterator position, size_type n, value_type const& x);
        template <class InputIterator>
          void    insert(iterator position, InputIterator first, InputIterator last);
        void      pop_front();
        void      pop_back();
        void      erase(iterator position);
        void      erase(iterator first, iterator last);
        void      swap(avl_tree<Tp, Hierarchy>&);
        void      clear() { h.clear(); }
      };
      
      template <class T, class Hierarchy>
        bool operator==(  avl_tree<T, Hierarchy> const& x,
                          avl_tree<T, Hierarchy> const& y);
      template <class T, class Hierarchy>
        bool operator< (  avl_tree<T, Hierarchy> const& x,
                          avl_tree<T, Hierarchy> const& y);
      template <class T, class Hierarchy>
        bool operator!=(  avl_tree<T, Hierarchy> const& x,
                          avl_tree<T, Hierarchy> const& y);
      template <class T, class Hierarchy>
        bool operator> (  avl_tree<T, Hierarchy> const& x,
                          avl_tree<T, Hierarchy> const& y);
      template <class T, class Hierarchy>
        bool operator>=(  avl_tree<T, Hierarchy> const& x,
                          avl_tree<T, Hierarchy> const& y);
      template <class T, class Hierarchy>
        bool operator<=(  avl_tree<T, Hierarchy> const& x,
                          avl_tree<T, Hierarchy> const& y);
    
      // specialized algorithms:
      template <class T, class Hierarchy>
        void swap(  avl_tree<T, Hierarchy>& x,
                    avl_tree<T, Hierarchy>& y);
    
    } // namespace tr2
    } // namespace std
    
    23.X.4.3.4.1 Balancing adaptor constructors, copy, and assignment [tr.hierarchy.balance.cons]
        explicit avl_tree (hierarchy_type const& = hierarchy_type());
        template <class InputIterator>
          avl_tree (InputIterator first, InputIterator last,
            hierarchy_type const& = hierarchy_type());
        avl_tree (avl_tree<T, Hierarchy> const& x);
    
    1. Effects: constructs a balanced tree equal to the range [first, last).

    2. Complexity: Linear.

          template <class InputIterator>
            void assign(InputIterator first, InputIterator last);
      
    3. Effects:

      clear(); 
      while(first++ != last)
        insert(end(), *first);
      
    23.X.4.3.4.2 Balancing adaptor map operations [tr.hierarchy.balance.map]
        iterator find(const value_type& x);
        const_iterator find(const value_type& x) const;
        template <class Cmp>
          iterator find(const value_type& x, Cmp cmp);
        const_iterator find(const value_type& x) const;
    
        size_type count(const value_type& x) const;
        template <class Cmp>
          size_type count(const value_type& x, Cmp cmp) const;
    
        iterator lower_bound(const value_type& x);
        const_iterator lower_bound(const value_type& x) const;
        template <class Cmp>
          iterator lower_bound(const value_type& x, Cmp cmp);
        template <class Cmp>
          const_iterator lower_bound(const value_type& x, Cmp cmp) const;
    
        iterator upper_bound(const value_type& x);
        const_iterator upper_bound(const value_type& x) const;
        template <class Cmp>
          iterator upper_bound(const value_type& x, Cmp cmp);
        template <class Cmp>
          const_iterator upper_bound(const value_type& x, Cmp cmp) const;
    
        pair<iterator,iterator> equal_range(const value_type& x);
        pair<const_iterator,const_iterator>
          equal_range(const value_type& x) const;
        template <class Cmp>
          pair<iterator,iterator>
            equal_range(const value_type& x, Cmp cmp);
        template <class Cmp>
          pair<const_iterator,const_iterator>
            equal_range(const value_type& x, Cmp cmp) const;
    
    1. Notes: The find, lower_bound, upper_bound and equal_range member functions each have four versions, differing in whether they return an iterator or a const_iterator, and if they take a cmp function object argument or not (count comes only in the latter two variants, as it returns a size_type, not an iterator). In each case the behavior of the four (two) functions is in principle identical.

    2. Complexity: logarithmic (with the exception of count, which is log(size()) + count(x)

    23.X.4.3.4.3 Balancing adaptor modifiers [tr.hierarchy.balance.modifiers]
        void      push_front(value_type const& x);
        void      push_back(value_type const& x);
        iterator  insert(iterator position, value_type const& x = value_type());
    
    1. Complexity: amortized constant

          void      insert(iterator position, size_type n, value_type const& x);
          template <class InputIterator>
            void    insert(iterator position, InputIterator first, InputIterator last);    
      
    2. Complexity: linear in the number of elements to insert

          void      pop_front();
          void      pop_back();
          void      erase(iterator position);
      
    3. Complexity: amortized constant

          void      erase(iterator first, iterator last);
      
    4. Complexity: log(size())+ N where N is the distance from first to last

          void      clear();
      
    5. Complexity: log(size())+ N

    23.X.4.3.4.4 Balancing adaptor specialized algorithms [tr.hierarchy.balance.special]
        template <class T, class Hierarchy>
          void swap(  avl_tree<T, Hierarchy>& x,
                      avl_tree<T, Hierarchy>& y);
    
    1. Effects: x.swap(y);

    24 Iterators library[tr.iterators]

    Add before subclause 24.4, Predefined iterators ([lib.predef.iterators]):

    24.X Cursors [tr.cursors]

    1. Cursors provide a uniform way of applying algorithms to hierarchical data structures. In order to also allow for algorithms relevant when dealing with linear data structures, any cursor class is actually a refinement of a corresponding iterator class.

    2. If exactly one application of the expression i = i.begin(), followed by a finite sequence of applications of the expression ++j makes i == j, j is a child (or immediate descendant ) of i, and i is the parent (or the immediate ancestor) of j. A cursor j is another cursor i's descendant if there is a finite sequential combination of applications of either of the expressions ++i and i = i.begin() that makes i == j; i is then called j's ancestor. If two cursors i and j share at least one common ancestor, they refer to the same container. The descending traversal capabilities of a class relate to the range of children of a given instance of that class.

    3. In addition to a cursor's descending traversal tags, two of them are reused to indicate a cursor's ascending traversal abilities, namely forward and bidirectional traversal in order to indicate whether a given cursor provides traversal to the parent.

    4. Apart from cursors that are past-the-end (like their iterator counterparts can be), the notion of a cursor on-top is introduced, denoting a cursor that is ancestor to all other cursors within a hierarchy is introduced; and just as for past-the-end ones, the library generally does not assume on-top cursors be dereferenceable.

    5. A cursor c for which c.emtpy() == true is called leaf cursor. A leaf cursor's children are never assumed to be dereferenceable. A cursor which is either on-top or a descendant of an on-top cursor, but in either case not a leaf cursor, nor a descendant of a leaf cursor, is called an internal cursor.

    6. A cursor, like an iterator, can have a singular value that is not associated with any hierarchy, meaning that most expressions are undefined for it, with the exception of assignment of a non-singular value to a cursor that holds a singular value. The children of a leaf cursor's child are never assumed to be non-singular; nor is the parent of an on-top node.

    7. Like for iterators, the Standard defines a number of categories of cursors according to the operations defined on them: cursor, descending cursor, descending forward cursor, descending bidirectional cursor, descending random access cursor, ascending cursor, ascending forward cursor, ascending bidirectional , and ascending random access cursor. The cursors of any ascending category generally support all the operations of their descending counterpart, plus a method to obtain their parent; relations between the forward, bidirectional and random access parts are as for iterators of those categories.

    8. In the following sections X denotes a cursor over values of type T, a and b denotes an identifier, r denotes a value of T& and t denotes a value of type T.

    24.X.1 Cursor requirements[tr.cursor.requirements]

    1. A class X satisfies the requirements of a cursor if the following expressions are valid, as shown in Table 8, in addition to satisfying the requirements of input iterators ([lib.input.iterators]) and output iterators ([lib.output.iterators]):

      Table 8: Cursor requirements (in addition to input and output iterators)
      expression return type operational semantics assertion/note
      pre/post-condition
      X::value_type T Any non-reference, non-cv-qualified type compile time
      X::type Convertible to cursor_tag, input_iterator_tag, and output_iterator_tag compile time
      X::cursor Convertible to X compile time
      X::const_cursor Convertible to const X compile time
    24.X.1.1 Descending Cursor [tr.descending.cursors]
    1. A class X satisfies the requirements of a descending cursor if, in addition to satisfying the requirements for cursors ([tr.cursor.requirements]) it also conforms to the container requirements ([lib.container.requirements]) with the exception of the following expressions:

      Table 9: Container requirements that are not supported
      unsupported expression
      X::iterator
      X::const_iterator
      X::reverse_iterator
      X::reverse_const_iterator
      (&a)->~X();
      X(a);
      X u(a);
      X u = a;
      a.begin()
      a.end()
      a.rbegin()
      a.rend()
      a == b
      a != b
      a.swap(b)
      r = a
      a < b
      a > b
      a <= b
      a >= b

      Notes: The expressions a.begin() and a.end() are, as shown in Table 9, replaced with equivalent expressions for cursors.

    2. Additionally, for a descending cursor, the following expression are valid, as shown in Table 10:

      Table 10: Descending cursor requirements (in addition to cursor)
      expression return type operational semantics assertion/note
      pre/post-condition
      X::type Convertible to descending_cursor_tag compile time
      a.begin() cursor or const_cursor for constant a pre: a is non-leaf. constant
      a.end() cursor or const_cursor for constant a pre: a is non-leaf. constant
      a.cbegin() const_cursor pre: a is non-leaf. constant
      a.cend() const_cursor pre: a is non-leaf. constant
      a.parity() size_type std::distance(b.begin(), a) if b is a's parent.
      pre: a is non-on-top.
      Linear in b.size()
    3. a.begin() returns the first child cursor of a. a.end() returns the past-the-end cursor for a. If a.empty(), then a.begin() == a.end();
    24.X.1.2 Descending Forward Cursor [tr.descending.forward.cursors]
    1. A class type X satisfies the requirements of a descending forward cursor if the following expressions are valid, as shown in Table 11, in addition to the requirements of descending cursors ([tr.descending.cursors]) and forward iterators ([lib.forward.iterators]):

      Table 11: Descending forward cursor requirements (in addition to descending cursors and forward iterators)
      expression return type operational semantics assertion/note
      pre/post-condition
      X::type Convertible to descending_forward_cursor_tag and forward_iterator_tag compile time
    24.X.1.3 Descending Bidirectional Cursor [tr.descending.bidirectional.cursors]
    1. A class type X satisfies the requirements of a descending bidirectional cursor if the following expressions are valid, as shown in Table 12, in addition to satisfying the requirements for descending forward cursors ([tr.descending.forward.cursors]) and bidirectional iterators ([lib.bidirectional.iterators]):

      Table 12: Descending bidirectional cursor requirements (in addition to forward descending cursors and bidirectional iterators)
      expression return type operational semantics assertion/note
      pre/post-condition
      X::type Convertible to descending_bidirectional_cursor_tag and bidirectional_iterator_tag compile time
      rbegin() and rend() do not seem very useful for multiway trees, as they hide end() and its possible children. Are different semantics or maybe having rend() stand in for end() sensible solutions? Or just ignore this aspect?
    24.X.1.4 Descending Random Access Cursor [tr.descending.random.access.cursors]
    1. A class type X satisfies the requirements of a descending random access cursor if the following expressions are valid, as shown in Table 13, in addition to satisfying the requirements for descending bidirectional cursors ([tr.descending.bidirectional.cursors]) and random access iterators ([lib.random.access.iterators]):

      Table 13: Descending random access cursor requirements (in addition to descending bidirectional cursors and random access iterators)
      expression return type operational semantics assertion/note
      pre/post-condition
      X::type Convertible to descending_random_access_cursor_tag and random_access_iterator_tag compile time
    24.X.1.5 Ascending Cursor [tr.ascending.cursors]
    1. A class type X satisfies the requirements of an ascending cursor if the following expressions are valid, as shown in Table 14, in addition to satisfying the requirements for descending cursors ([tr.descending.cursors]):

      Table 14: Ascending cursor requirements (in addition to descending cursors)
      expression return type operational semantics assertion/note
      pre/post-condition
      X::type Convertible to ascending_cursor_tag compile time
      a.parent() cursor; const_cursor for a constant a (Note A)
      !r X& r = r.parent(); pre: r is an internal, non-on-top cursor.
      post: r is internal.
      r == s and r is internal and non-on-top implies !r == !s.
      &r == &!r
      (Note A)

      Notes: Those entries marked "(Note A)" should have at worst linear complexity. See the individual hierarchy containers for specific complexity.

    24.X.1.6 Ascending Forward Cursor [tr.ascending.forward.cursors]
    1. A class type X satisfies the requirements of an ascending forward cursor if the following expressions are valid, as shown in Table 15, in addition to satisfying the requirements for ascending cursors ([tr.ascending.cursors]) and descending forward cursors ([tr.descending.forward.cursors]):

      Table 15: Ascending forward cursor requirements (in addition to ascending cursors and descending forward cursors)
      expression return type operational semantics assertion/note
      pre/post-condition
      X::type Convertible to ascending_forward_cursor_tag compile time
    24.X.1.7 Ascending Bidirectional Cursor [tr.ascending.bidirectional.cursors]
    1. A class type X satisfies the requirements of an ascending bidirectional cursor if the following expressions are valid, as shown in Table 16, in addition to satisfying the requirements of ascending forward cursors ([tr.ascending.forward.cursors]) and descending bidirectional cursors ([tr.descending.bidirectional.cursors]):

      Table 16: Ascending bidirectional cursor requirements (in addition to ascending forward cursors and descending bidirectional cursors)
      expression return type operational semantics assertion/note
      pre/post-condition
      X::type Convertible to ascending_bidirectional_cursor_tag compile time
    24.X.1.8 Ascending Random Access Cursor [tr.ascending.random.access.cursors]
    1. A class type X satisfies the requirements of an ascending random access cursor if the following expressions are valid, as shown in Table 17, in addition to satisfying the requirements for ascending bidirectional cursors ([tr.ascending.bidirectional.cursors]) and descending random access cursors ([tr.descending.random.access.cursors]):

      Table 17: Ascending random access cursor requirements (in addition to ascending bidirectional cursors and descending random access cursors)
      expression return type operational semantics assertion/note
      pre/post-condition
      X::type Convertible to ascending_random_access_cursor_tag compile time

    24.X.2 Cursor flavors [tr.cursor.flavors]

    1. A cursor that satisfies at least the descending cursor requirements ([tr.descending.cursors]) can be either a plain cursor or a multiway cursor. If the expressions a.begin(), a.cbegin(), a.end() and a.cend() are valid for any internal cursor a of type X, except for past-the-end ones, X satisfies the plain cursor requirements. If those expressions are valid for any internal cursor including past-the-end ones, X satisfies the multiway cursor requirements.

    24.X.3 Header <cursor> synopsis [tr.cursor.synopsis]

    namespace std {
    namespace tr2 {
      template <class Cursor> struct cursor_value;
      template <class Cursor> struct cursor_reference;
      template <class Cursor> struct cursor_const_reference;
      template <class Cursor> struct cursor_pointer;
      template <class Cursor> struct cursor_difference;
      template <class Cursor> struct cursor_size;
      template <class Cursor> struct cursor_category;
    
      template <class Category, class T, class Distance = ptrdiff_t,
                class Size = size_t, class Pointer = T*,
                class Reference = T&> struct cursor;
    
      struct cursor_tag 
        : public input_iterator_tag, public output_iterator_tag {};
      struct descending_cursor_tag
        : public cursor_tag {};
      struct descending_forward_cursor_tag
        : public descending_cursor_tag, public forward_iterator_tag {};
      struct descending_bidirectional_cursor_tag
        : public descending_cursor_tag, public bidirectional_iterator_tag {};
      struct descending_random_access_cursor_tag
        : public descending_cursor_tag, public random_access_iterator_tag {};
      struct ascending_cursor_tag
            : public descending_cursor_tag {};
      struct ascending_forward_cursor_tag
        : public descending_forward_cursor_tag {};
      struct ascending_bidirectional_cursor_tag
        : public descending_bidirectional_cursor_tag {};
      struct ascending_random_access_cursor_tag
        : public descending_random_access_cursor_tag {};
    } // namespace tr2
    } // namespace std
    

    24.X.4 Cursor primitives [tr.cursor.primitives]

    1. To simplify the task of defining cursors, the library provides several classes and functions:

    24.X.4.1 Cursor traits [tr.cursor.traits]
    1. The following classes are required to be defined appropriately for a cursor of type Cursor:

      template <class Cursor> struct cursor_value {
        typedef typename Cursor::value_type type;
      };
      
      template <class Cursor> struct cursor_reference {
        typedef typename Cursor::reference type;
      };
      
      template <class Cursor> struct cursor_const_reference {
        typedef typename Cursor::const_reference type;
      };
      
      template <class Cursor> struct cursor_pointer {
        typedef typename Cursor::pointer type;
      };
      
      template <class Cursor> struct cursor_difference {
        typedef typename Cursor::difference_type type;
      };
      
      template <class Cursor> struct cursor_size {
        typedef typename Cursor::size_type type;
      };
      
      template <class Cursor> struct cursor_category {
        typedef typename Cursor::cursor_category type;
      };
      
    24.X.4.2 Basic cursor [tr.cursor.basic]
    1. The cursor template may be used as a base class to ease the definition of required types for new cursors.

      namespace std {
      namespace tr2 {
        template <class Category, class T, class Distance = ptrdiff_t,
                  class Size = size_t, class Pointer = T*,
                  class Reference = T&>
        struct cursor {
          typedef Category  cursor_category;
          typedef T         value_type;
          typedef Distance  difference_type;
          typedef Size      size_type;
          typedef Pointer   pointer;
          typedef Reference reference;
        };
      } // namespace tr2
      } // namespace std
      
    24.X.4.3 Standard cursor tags [tr.cursor.tags]
    1. Cursor tags pick up the notion of iterator tags ([lib.std.iterator.tags]) and extend them by adding information about a given cursor class' descending or ascending traversal capabilities ([tr.cursor.requirements]). This yields the cursor tags cursor_tag, descending_cursor_tag, descending_forward_cursor_tag, descending_bidirectional_cursor_tag, descending_random_access_cursor_tag, ascending_cursor_tag, ascending_forward_cursor_tag, ascending_bidirectional_cursor_tag and ascending_random_access_cursor_tag. For every cursor of type Cursor, cursor_category<Cursor>::type must be defined to be the most specific category tag that describes the cursor's behavior.

      namespace std {
      namespace tr2 {
        struct cursor_tag 
          : public input_iterator_tag, public output_iterator_tag {};
        struct descending_cursor_tag
          : public cursor_tag {};
        struct descending_forward_cursor_tag
          : public descending_cursor_tag, public forward_iterator_tag {};
        struct descending_bidirectional_cursor_tag
          : public descending_cursor_tag, public bidirectional_iterator_tag {};
        struct descending_random_access_cursor_tag
          : public descending_cursor_tag, public random_access_iterator_tag {};
        struct ascending_cursor_tag
              : public descending_cursor_tag {};
        struct ascending_forward_cursor_tag
          : public descending_forward_cursor_tag {};
        struct ascending_bidirectional_cursor_tag
          : public descending_bidirectional_cursor_tag {};
        struct ascending_random_access_cursor_tag
          : public descending_random_access_cursor_tag {};
      } // namespace tr2
      } // namespace std
      

    24.2 Header <iterator> synopsis [lib.iterator.synopsis]

    Append to section introduced with // subclause 24.4, predefined iterators:

    namespace std {
    namespace tr2 {
    
    
    namespace preorder {
      template <class Cursor> class iterator;
    
      template <class Cursor>
        bool operator==(
          const iterator<Cursor>& x,
          const iterator<Cursor>& y);
    
      template <class Cursor>
        bool operator!=(
          const iterator<Cursor>& x,
          const iterator<Cursor>& y);
    } // namespace preorder   
    
    namespace postorder {
      template <class Cursor> class iterator;
    
      template <class Cursor>
      bool operator==(
        const iterator<Cursor>& x,
        const iterator<Cursor>& y);
    
      template <class Cursor>
      bool operator!=(
        const iterator<Cursor>& x,
        const iterator<Cursor>& y);
    } // namespace postorder   
    
    namespace inorder {
      template <class Cursor> class iterator;
    
      template <class Cursor>
      bool operator==(
        const iterator<Cursor>& x,
        const iterator<Cursor>& y);
    
      template <class Cursor>
      bool operator!=(
        const iterator<Cursor>& x,
        const iterator<Cursor>& y);
    } // namespace inorder
    
    } // namespace tr2
    } // namespace std
    

    24.4.X Linear order traversal iterators [tr.order.iterators]

    1. For linear traversal of hierarchies, the library offers a number of useful predefined iterators, namely for preorder, postorder and inorder traversal in namespaces named accordingly.

    2. Preorder traversal means that after a given element, first the subtree to its left, then the one to its right will be visited.

    3. Postorder traversal means that before a given element, first the subtree to its left, then the one to its right will be visited.

    4. Inorder traversal means that a given element will be visited after the subtree to its left and before the one to its right will be visited.

    5. For each of the above kinds of traversal order, the library offers a kind of order traversal iterator adaptor template class whose template parameter is a bidirectional or random access (either ascending or descending) cursor class. Increment and decrement operations for these iterator adaptor classes are implemented to allow stepwise iteration according to the respective requirements.

    24.4.X.1 Template class iterator [tr.order.iterator]
    1. In the following, the template class iterator and related operators only as in namespace preorder are shown. Note that template classes and operators of same name and interface must also be present in namespace postorder as well as in namespace inorder.

      namespace std {
      namespace tr2 {
      
      namespace preorder {
        template <class Cursor>
        class iterator :
          public iterator< /* see Note A */, 
                          typename iterator_traits<Cursor>::value_type,
                          typename iterator_traits<Cursor>::difference_type,
                          typename iterator_traits<Cursor>::pointer,
                          typename iterator_traits<Cursor>::reference> {
        protected:
          Cursor current;
        public:
          typedef Cursor cursor_type;
          iterator();
          explicit iterator(Cursor x);
          
          Cursor base() const;         // explicit
          Reference operator*() const;
          Pointer   operator->() const;
          
          iterator& operator++();
          iterator  operator++(int);
          iterator& operator--();
          iterator  operator--(int);
        };
      
      template <class Cursor>
        bool operator==(
          const iterator<Cursor>& x,
          const iterator<Cursor>& y);
      
      template <class Cursor>
        bool operator!=(
          const iterator<Cursor>& x,
          const iterator<Cursor>& y);
      
      } // namespace preorder
      
      } // namespace tr2
      } // namespace std
      

      Note A: If typename iterator_traits<Cursor>::iterator_category is equivalent to random_access_iterator_tag, put in bidirectional_iterator_tag; otherwise put in typename iterator_traits<Cursor>::iterator_category.

    24.4.X.2 Linear order iterator requirements [tr.order.iter.requirements]
    1. The template parameter Cursor shall meet all the requirements of an Ascending Forward Cursor ([tr.ascending.forward.cursors]). Additionally, for the template class and operators in namespace inorder, the template parameter Cursor must be a Multiway Cursor ([tr.cursor.flavors]).

    2. Additionally, Cursor shall meet the requirements of a Ascending Bidirectional Cursor ([tr.ascending.bidirectional.cursors]) if the member operator-- (24.4.X.3.7) is referenced in a way that requires instantiation (14.7.1).

    24.4.X.3 inorder::iterator operations [tr.order.iter.ops]
    24.4.X.3.1 inorder::iterator constructor [tr.order.iter.cons]
        explicit iterator(Cursor x);
    
    1. Effects: Initializes current with x.

    24.4.X.3.2 Conversion [tr.order.iter.conv]
        Iterator base() const; // explicit
    
    1. Returns: current

    24.4.X.3.3 operator* [tr.order.iter.op.star]
        Reference operator*() const;
    
    1. Returns: *current

    24.4.X.3.4 operator-> [tr.order.iter.opref]
        Pointer operator->() const;
    
    1. Returns: &(operator*())

    24.4.X.3.5 operator++ [tr.order.iter.op++]
        iterator& operator++() const;
    
    1. Effects: Sets current to the next cursor in the given order.

    2. Returns: *this

        iterator operator++(int) const;
    
    1. Effects:

      iterator tmp = *this;
      this->operator++();
      return tmp;
      
    24.4.X.3.6 operator-- [tr.order.iter.op--]
        iterator& operator++() const;
    
    1. Effects: Sets current to the previous cursor in the given order.

    2. Returns: *this

      iterator operator--(int) const;
    
    1. Effects:

      iterator tmp = *this;
      this->operator--();
      return tmp;
      
    24.4.X.3.7 operator== [tr.order.iter.op==]
        template <class Cursor>
          bool operator==(
            const iterator<Cursor>& x,
            const iterator<Cursor>& y);
    
    1. Returns: x.current == y.current

    24.4.X.3.8 operator!= [tr.order.iter.op!=]
        template <class Cursor>
          bool operator!=(
            const iterator<Cursor>& x,
            const iterator<Cursor>& y);
    
    1. Returns: x.current != y.current

25 Algorithms library [tr.algorithm]

Append to paragraph 2, Header <iterator> synopsis, after // subclause 25.1, non-modifying sequence operations.
// subclause 2.X, non-modifying hierarchy operations
namespace std {
namespace tr2 {

namespace preorder {
  template <class Hierarchy>
    iterator<typename Hierarchy::cursor>
      begin(Hierarchy& h);
  template <class Hierarchy>
    iterator<typename Hierarchy::const_cursor>
      cbegin(Hierarchy const& h);
  
  template <class Hierarchy>
    iterator<typename Hierarchy::cursor>
      end(Hierarchy& h);
  template <class Hierarchy>
    iterator<typename Hierarchy::const_cursor>
      cend(Hierarchy const& h);
} // namespace preorder

namespace postorder {
  template <class Hierarchy>
    iterator<typename Hierarchy::cursor>
      begin(Hierarchy& h);
  template <class Hierarchy>
    iterator<typename Hierarchy::const_cursor>
      cbegin(Hierarchy const& h);
  
  template <class Hierarchy>
    iterator<typename Hierarchy::cursor>
      end(Hierarchy& h);
  template <class Hierarchy>
    iterator<typename Hierarchy::const_cursor>
      cend(Hierarchy const& h);
} // namespace postorder

namespace inorder {
  template <class MultiwayHierarchy>
    iterator<typename MultiwayHierarchy::cursor>
      begin(MultiwayHierarchy& m);
  template <class MultiwayHierarchy>
    iterator<typename MultiwayHierarchy::const_cursor>
      cbegin(MultiwayHierarchy const& m);
  
  template <class MultiwayHierarchy>
    iterator<typename MultiwayHierarchy::cursor>
      end(MultiwayHierarchy& m);
  template <class MultiwayHierarchy>
    iterator<typename MultiwayHierarchy::const_cursor>
      cend(MultiwayHierarchy const& m);
} // namespace inorder

} // namespace tr2
} // namespace std
[c]rbegin(...) and [c]rend(..) are not provided as they can be achieved via reverse_iterator({[c]begin(...)|[c]end(...)}) (which also defines requirements when this is possible)
Change paragraph 3 to read:

All of the algorithms are separated from the particular implementations of data structures and are parameterized by iterator or hierarchy types. Because of this, they can work with program defined data structures, as long as these data structures have iterator or cursor types satisfying the assumptions on the algorithms.

Append to paragraph 4:

If an algorithm's template parameter is Hierarchy, the actual template argument shall satisfy the requirements of a hierarchy ([tr.hierarchy.req]). If an algorithm's template parameter is MultiwayHierarchy, the actual template argument shall satisfy the requirements of a multiway hierarchy ([tr.hierarchy.multiway]).

25.X Non-modifying hierarchy algorithms [tr.alg.hierarchy]

25.X.1 Non-modifying hierarchy preorder range algorithms [tr.alg.hier.preorder]

25.X.1.1 Preorder begin [tr.alg.hier.pre.begin]
    namespace std {
    namespace tr2 {
    namespace preorder {
      template <class Hierarchy>
        iterator<typename Hierarchy::cursor>
          begin(Hierarchy& h);
      template <class Hierarchy>
        iterator<typename Hierarchy::const_cursor>
          cbegin(Hierarchy const& h);
    } // namespace preorder
    } // namespace tr2
    } // namespace std
  1. Returns: An iterator pointing to the first element of h in preorder.

  2. Complexity: constant

25.X.1.2 Preorder end [tr.alg.hier.pre.end]
    namespace std {
    namespace tr2 {
    namespace preorder { 
      template <class Hierarchy>
        iterator<typename Hierarchy::cursor>
          end(Hierarchy& h);
      template <class Hierarchy>
        iterator<typename Hierarchy::const_cursor>
          cend(Hierarchy const& h);
    } // namespace preorder
    } // namespace tr2
    } // namespace std
  1. Returns: An iterator pointing one position past the last element of h in preorder.

  2. Complexity: linear

25.X.2 Non-modifying hierarchy postorder range algorithms [tr.alg.hier.postorder]

25.X.2.1 Postorder begin [tr.alg.hier.post.begin]
    namespace std {
    namespace tr2 {
    namespace postorder {
      template <class Hierarchy>
        iterator<typename Hierarchy::cursor>
          begin(Hierarchy& h);
      template <class Hierarchy>
        iterator<typename Hierarchy::const_cursor>
          cbegin(Hierarchy const& h);
    } // namespace postorder
    } // namespace tr2
    } // namespace std
  1. Returns: An iterator pointing to the first element of h in postorder.

  2. Complexity: linear

25.X.2.2 Postorder end [tr.alg.hier.post.end]
    namespace std {
    namespace tr2 {
    namespace postorder { 
      template <class Hierarchy>
        iterator<typename Hierarchy::cursor>
          end(Hierarchy& h);
      template <class Hierarchy>
        iterator<typename Hierarchy::const_cursor>
          cend(Hierarchy const& h);
    } // namespace postorder
    } // namespace tr2
    } // namespace std
  1. Returns: An iterator pointing one position past the last element of h in postorder.

  2. Complexity: constant

25.X.2 Non-modifying hierarchy inorder range algorithms [tr.alg.hier.inorder]

25.X.2.1 Inorder begin [tr.alg.hier.in.begin]
    namespace std {
    namespace tr2 {
    namespace inorder {
      template <class MultiwayHierarchy>
        iterator<typename MultiwayHierarchy::cursor>
          begin(MultiwayHierarchy& m);
      template <class MultiwayHierarchy>
        iterator<typename MultiwayHierarchy::const_cursor>
          cbegin(MultiwayHierarchy const& m);
    } // namespace inorder
    } // namespace tr2
    } // namespace std
  1. Returns: An iterator pointing to the first element of h in inorder.

  2. Complexity: linear

25.X.2.2 Inorder end [tr.alg.hier.in.end]
    namespace std {
    namespace tr2 {
    namespace inorder { 
      template <class MultiwayHierarchy>
        iterator<typename MultiwayHierarchy::cursor>
          end(MultiwayHierarchy& m);
      template <class MultiwayHierarchy>
        iterator<typename MultiwayHierarchy::const_cursor>
          cend(MultiwayHierarchy const& m);
    } // namespace inorder
    } // namespace tr2
    } // namespace std
  1. Returns: An iterator pointing one position past the last element of h in inorder.

  2. Complexity: linear

References

[austern]
Austern, Matthew H.; Stroustrup, Bjarne; Thorup, Mikkel; Wilikinson, John. Untangling the Balancing and Searching of Balanced Binary Search Trees, Software: Practice and Experience 33(13): 1273-1298 (2003)
Electronic Appendix: http://www.research.att.com/~bs/tree-appendix.pdf
[cormen]
Cormen, Thomas H.; Leiserson, Charles E.; Rivest, Ronald L.; Stein, Clifford. Introduction to Algorithms. Second Edition (MIT Press, 2001)
[dreizin]
Dreizin, Vladimir; Kosnik, Benjamin; Tavory, Ami. Policy-Based Data Structures, http://gcc.gnu.org/onlinedocs/libstdc++/ext/pb_ds/
[ekman]
Ekman, Rasmus. Structured Associative Containers, http://www.abc.se/~re/code/tst
[gottschlich]
Gottschlich, Justin. C++ Trees, http://www.gamedev.net/reference/articles/article2192.asp and http://www.gamedev.net/reference/articles/article2233.asp
[haas]
Haas, Mitchell. Tree Container Library, http://www.datasoftsolutions.net/tree_container_library/overview.php
[karas]
Karas, Walt. C++ AVL Tree Template, http://us.geocities.com/wkaras/gen_cpp/avl_tree.html
[knuth97]
Knuth, Donald E. The Art of Computer Programming. Volume 1: Fundamental Algorithms. Third Edition (Reading, Massachusetts: Addison-Wesley, 1997)
[knuth98]
Knuth, Donald E. The Art of Computer Programming. Volume 3: Sorting and Searching. Second Edition (Reading, Massachusetts: Addison-Wesley, 1998)
[mirwaisi]
Mirwaisi, Jeff. treelib, https://boost-consulting.com:8443/trac/soc/attachment/wiki/tree/resources/trees/treelib.tar.bz2
[parent]
Parent, Sean et al. forest, http://opensource.adobe.com/group__forest__related.html
[peeters]
Peeters, Kasper. tree.hh: an STL-like C++ tree class, http://www.aei.mpg.de/~peekas/tree/
[rivera]
Rivera, René. RankTree.h, http://redshift-software.com/~grafik/RankTree.h