// Filename: ordered_vector.h // Created by: drose (20Feb02) // //////////////////////////////////////////////////////////////////// // // PANDA 3D SOFTWARE // Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved // // All use of this software is subject to the terms of the Panda 3d // Software license. You should have received a copy of this license // along with this source code; you will also find a current copy of // the license at http://www.panda3d.org/license.txt . // // To contact the maintainers of this program write to // panda3d@yahoogroups.com . // //////////////////////////////////////////////////////////////////// #ifndef ORDERED_VECTOR_H #define ORDERED_VECTOR_H #include "pandabase.h" #include "config_util.h" #include "pvector.h" #include "pset.h" #include //////////////////////////////////////////////////////////////////// // Class : ordered_vector // Description : This template class presents an interface similar to // the STL set or multiset (and ov_set and ov_multiset // are implemented specifically, below), but it is // implemented using a vector that is kept always in // sorted order. // // In most cases, an ov_set or ov_multiset may be // dropped in transparently in place of a set or // multiset, but the implementation difference has a few // implications: // // (1) The ov_multiset will maintain stability of order // between elements that sort equally: they are stored // in the order in which they were added, from back to // front. // // (2) Insert and erase operations into the middle of // the set can be slow, just as inserting into the // middle of a vector can be slow. In fact, building up // an ov_set by inserting elements one at a time is an // n^2 operation. On the other hand, building up an // ov_set by adding elements to the end, one at time, is // somewhat faster than building up a traditional set; // and you can even add unsorted elements with // push_back() and then call sort() when you're done, // for a log(n) operation. // // (3) Iterators may not be valid for the life of the // ordered_vector. If the vector reallocates itself, // all iterators are invalidated. // // (4) Random access into the set is easy with the [] // operator. //////////////////////////////////////////////////////////////////// template > class ordered_vector { private: typedef pvector Vector; public: // Typedefs typedef Key key_type; typedef Key value_type; typedef Key &reference; typedef const Key &const_reference; typedef Compare key_compare; typedef Compare value_compare; // Be careful when using the non-const iterators that you do not // disturb the sorted order of the vector, or that if you do, you // call sort() when you are done. typedef Vector::iterator iterator; typedef Vector::const_iterator const_iterator; typedef Vector::reverse_iterator reverse_iterator; typedef Vector::const_reverse_iterator const_reverse_iterator; typedef Vector::difference_type difference_type; typedef Vector::size_type size_type; public: // Constructors. We don't implement the whole slew of STL // constructors here yet. INLINE ordered_vector(const Compare &compare = Compare()); INLINE ordered_vector(const ordered_vector ©); INLINE ordered_vector &operator = (const ordered_vector ©); INLINE ~ordered_vector(); // Iterator access. INLINE iterator begin(); INLINE iterator end(); INLINE reverse_iterator rbegin(); INLINE reverse_iterator rend(); INLINE const_iterator begin() const; INLINE const_iterator end() const; INLINE const_reverse_iterator rbegin() const; INLINE const_reverse_iterator rend() const; // Random access. INLINE reference operator [] (size_type n); INLINE const_reference operator [] (size_type n) const; // Size information. INLINE size_type size() const; INLINE size_type max_size() const; INLINE bool empty() const; // Equivalence and lexicographical comparisons. INLINE bool operator == (const ordered_vector &other) const; INLINE bool operator != (const ordered_vector &other) const; INLINE bool operator < (const ordered_vector &other) const; INLINE bool operator > (const ordered_vector &other) const; INLINE bool operator <= (const ordered_vector &other) const; INLINE bool operator >= (const ordered_vector &other) const; // Insert operations. iterator insert_unique(iterator position, const value_type &key); iterator insert_nonunique(iterator position, const value_type &key); INLINE pair insert_unique(const value_type &key); INLINE iterator insert_nonunique(const value_type &key); // Erase operations. INLINE iterator erase(iterator position); INLINE size_type erase(const key_type &key); INLINE void erase(iterator first, iterator last); INLINE void clear(); // Find operations. INLINE iterator find(const key_type &key); INLINE const_iterator find(const key_type &key) const; INLINE iterator find_particular(const key_type &key); INLINE const_iterator find_particular(const key_type &key) const; INLINE size_type count(const key_type &key) const; INLINE iterator lower_bound(const key_type &key); INLINE const_iterator lower_bound(const key_type &key) const; INLINE iterator upper_bound(const key_type &key); INLINE const_iterator upper_bound(const key_type &key) const; INLINE pair equal_range(const key_type &key); INLINE pair equal_range(const key_type &key) const; // Special operations. INLINE void swap(ordered_vector &other); INLINE void reserve(size_type n); INLINE void sort_unique(); INLINE void sort_nonunique(); INLINE void push_back(const value_type &key); private: INLINE iterator nci(const_iterator iterator); INLINE iterator find_insert_position(iterator first, iterator last, const key_type &key); iterator r_find_insert_position(iterator first, iterator last, const key_type &key); const_iterator r_find(const_iterator first, const_iterator last, const_iterator not_found, const key_type &key) const; const_iterator r_find_particular(const_iterator first, const_iterator last, const_iterator not_found, const key_type &key) const; size_type r_count(const_iterator first, const_iterator last, const key_type &key) const; const_iterator r_lower_bound(const_iterator first, const_iterator last, const key_type &key) const; const_iterator r_upper_bound(const_iterator first, const_iterator last, const key_type &key) const; pair r_equal_range(const_iterator first, const_iterator last, const key_type &key) const; INLINE bool verify_list(); #ifndef NDEBUG bool verify_list_impl(iterator first, iterator last); #endif // This function object is used in sort_unique(). It returns true // if two consecutive sorted elements are equivalent. class EquivalentTest { public: // For some reason, VC++ won't allow us to define these bodies // outside the class; they must be defined here. The error // message is C3206: "member functions of nested classes of a // template class cannot be defined outside the class". INLINE EquivalentTest(const Compare &compare) : _compare(compare) { } INLINE bool operator () (const key_type &a, const key_type &b) { nassertr(!_compare(b, a), false); return !_compare(a, b); } Compare _compare; }; Compare _compare; Vector _vector; }; //////////////////////////////////////////////////////////////////// // Class : ov_set // Description : A specialization of ordered_vector that emulates a // standard STL set: one copy of each element is // allowed. //////////////////////////////////////////////////////////////////// template > class ov_set : public ordered_vector { public: INLINE ov_set(const Compare &compare = Compare()); INLINE ov_set(const ov_set ©); INLINE ov_set &operator = (const ov_set ©); INLINE iterator insert(iterator position, const value_type &key); INLINE pair insert(const value_type &key); INLINE void sort(); }; //////////////////////////////////////////////////////////////////// // Class : ov_multiset // Description : A specialization of ordered_vector that emulates a // standard STL set: many copies of each element are // allowed. //////////////////////////////////////////////////////////////////// template > class ov_multiset : public ordered_vector { public: INLINE ov_multiset(const Compare &compare = Compare()); INLINE ov_multiset(const ov_multiset ©); INLINE ov_multiset &operator = (const ov_multiset ©); INLINE iterator insert(iterator position, const value_type &key); INLINE iterator insert(const value_type &key); INLINE void sort(); }; #include "ordered_vector.I" #include "ordered_vector.T" #endif