自平衡树Splaytrees的C++泛型实现

 

/* Good performance for a splay tree depends on the fact that it is self-balancing, and indeed self optimizing,

 * in that frequently accessed nodes will move nearer to the root where they can be accessed more quickly.

 * This is an advantage for nearly all practical applications, and is particularly useful for implementing caches

 * and garbage collection algorithms; however it is important to note that for uniform access, a splay tree's

 * performance will be considerably (although not asymptotically) worse than a somewhat balanced simple

 * binary search tree.

 

 * Splay trees also have the advantage of being considerably simpler to implement than other self-balancing

 * binary search trees, such as red-black trees or AVL trees, while their average-case performance is just

 * as efficient. Also, splay trees do not need to store any bookkeeping data, thus minimizing memory requi-

 * rements. However, these other data structures provide worst-case time guarantees, and can be more

 * efficient in practice for uniform access.

 */

 

 

/* Author: 窦小蹦(fairyroad)

 * Last update: June 03 09:00 EST 2010

 * E-mail: [email protected]

 */

 

 

#ifndef SPLAYTREE_H_

#define SPLAYTREE_H_

 

#include<algorithm>

#include "memory.h" /*This file mainly contains some allocator classes

                        which are used for managing memory or somthing.*/

 

namespace SP_tree

{

    template <class T>inline void swap(T& x, T& y)

    {

      T temp = x;

      x = y;

      y = temp;

    };

 

    template<class T, class U>struct pair

    {

          typedef T first_type;

          typedef U second_type;

          T first;

          U second;

          pair(const T& x = T(), const U& y = U()):first(x),second(y) {}

          template<class V, class W>pair(const pair<V, W>& pr):first(pr.first),second(pr.second) {}

    };

 

    template <class T>struct less{

            bool operator()(const T& x, const T& y) const { return x < y; } };

 

    template <class T>struct greater{

            bool operator()(const T& x, const T& y) const { return x > y; } };

 

}

 

using SP_tree::swap;

 

template <class Value>

struct Splaytree_node

{

    typedef Splaytree_node* link_type;

    Value data;

    link_type parent, left, right;

 

    Splaytree_node(const Value& _data = Value(), link_type p = 0, link_type l = 0,

                 link_type r = 0):

      data(_data),parent(p),left(l),right(r) {}

    Splaytree_node(const Splayree_node& _other):data(_other.data), parent(_other.parent),

      left(_other.left), right(_other.right) {}

 

      void swap_(Splaytree_node& rhs){

          ::swap(value,rhs.value);

          ::swap(parent,rhs.parent);

          ::swap(left,rhs.left);

          ::swap(right,rhs.right);

      }

    Splaytree_node& operator=(const Splaytree_node& x){

        Splaytree_node tmp(x);

        swap(tmp);

        return *this;

      }

 

    virtual ~Splaytree_node() {}

    static link_type minimum(link_type x){

        while(x->left) x = x->left;

        return x;

    }

    static link_type maximum(link_type x){

        while(x->right) x = x->right;

        return x;

    }

 

};//end of Splaytree_node

 

 

template <class Value, class Ref, class Ptr>

class Splaytree_iterator

{

protected:

    typename Splayree_node<Value>::link_type node;

 

public:

    typedef Value value_type;

    typedef Ref reference;

    typedef Ptr pointer;

    typedef Splaytree_iterator<Value,Value&,Value*> iterator;

    typedef Splaytree_iterator<Value,const Value&,const Value*> const_iterator;

    typedef Splayree_node<Value>* link_type;

    typedef Splaytree_iterator<Value,Ref,Ptr> self;

    typedef ::bidirectional_iterator_tag iterator_category;

    typedef ptrdiff_t difference_type;

 

public:

    void increment()//find the node

                //whose key has the smallest value among all those whose key is bigger than the oringinal's

    {

      if(node->right)

      {

        node = node->right;

        while(node->left) node = node->left;

      }

      else

      {

       link_type y = node->parent;

       while(node == y->right)

       {

         node = y;

         y = y->parent;

       }

       if(node->right != y) node = y;

     }

   }

 

   void decrement()// find the node whose key has the biggest value among all those whose key is smaller than the oringinal's

   {

     if(node == node->parent->parent)

       node = node->right;

     else if(node->left)//if the node has a left-child,walk to the end in the right-hand direction

     {

       link_type y = node->left;

       while(y->right) y = y->right;

       node = y;

     }

     else//does not have a left-child,go up until find a node that doesn't belong to its father's left-child

     {

       link_type y = node->parent;

       while(node == y->left)

       {

         node = y;

         y = y->parent;

       }

       node = y;

     }

   }

 

   Splaytree_iterator(link_type x = 0):node(x) {}

   Splaytree_iterator(const Splaytree_iterator& it):node(it) {}

 

   reference operator*()const { return node->data; }

   pointer operator->()const { return &(operator*()); }

 

   self& operator++()

   {

     increment();

     return *this;

   }

 

   self operator++(int)

   {

     self tmp = *this;

     increment();

     return tmp;

   }

 

   self& operator--()

   {

     decrement();

     return *this;

   }

 

   self operator--(int)

   {

     self tmp = *this;

     decrement();

     return tmp;

   }

 

private:

     friend bool operator==(const Splaytree_iterator& x, const Splaytree_iterator& y) {return x.node == y.node; }

     friend bool operator!=(const Splaytree_iterator& x, const Splaytree_iterator& y) {return x.node != y.node; }

};

//end of Splaytree_iterator

 

template <class Key, class Value, class KeyOfValue, class Compare = less<Key>, class  Alloc = allocator<Value> >

class Splaytree  //Splay Tree

{

public:

   typedef Key key_type;

   typedef Value value_type;

   typedef value_type* pointer;

   typedef const value_type* const_pointer;

   typedef value_type& reference;

   typedef const value_type& const_reference;

   typedef typename Splaytree_node<Value>::link_type link_type;

   typedef size_t size_type;

   typedef ptrdiff_t difference_type;

   typedef typename Splaytree_node<value_type, reference, pointer>::iterator iterator;

   typedef typename Splaytree_node<value_type, const_reference, const_pointer>::const_iterator const_iterator;

   typedef ::reverse_iterator<iterator> reverse_iterator;

   typedef ::reverse_iterator<const_iterator> const_reverse_iterator;

 

private:

     typedef typename Alloc::template rebind<Splaytree_node<Value> >::other allocator_type;

     allocator_type alloc;

 

     void release_node(link_type p)

     {

         alloc.destroy(p);//These two functions are defined in the memory.hpp file.

         alloc.deallocate(p, 0);//And their functions can be easily implied from their names.

     }

 

    //creat a node

     link_type get_node(const Value& _data = Value(), link_type p = 0, link_type l = 0, link_type r = 0)

     {

          link_type ptr = 0;

          try{

              ptr = alloc.allocate(sizeof(Splaytree_node<Value>));

//This function is defined in the memory.hpp file.

              alloc.construct(ptr, Splaytree_node<Value>(_data, p, l, r));//This function is defined in the memory.hpp file.

           }

          catch(){

              release_node(ptr);

              throw;

           }

          return ptr;

      }

 

     link_type clone_node(link_type x) { return get_node(x->data, x->parent, x->left, x->right); }//copy a node

 

     void init()

     {

         header = get_node();

         root() = 0;

         leftmost() = header;

         rightmost() = header;

      }

 

protected:

   // The member data of Splaytree

   size_type node_count;//records the amount of nodes in the tree

   link_type header;//an accessorial data used for complemention

   Compare key_compare;

 

   // These three functions are used for expediently getting the member of the head node.

   link_type& root() const { return header->parent; }

   link_type& leftmost() const { return header->left; }

   link_type& rightmost()const { return header->right; }

 

   // These five functions are used for expediently getting the member of node x.

   static link_type& left(link_type x) {return x->left; }

   static link_type& right(link_type x) { return x->right; }

   static link_type& parent(link_type x) { return x->parent; }

   static reference value(link_type x) { return x->data; }

   static const Key& key(link_type x) { return KeyOfValue()(value(x)); }

 

public:

   explicit Splaytree(const Compare& comp = Compare()) : node_count(0), key_compare(comp) { init(); }

   Splaytree(const Splaytree& x):node_count(0), key_compare(x.key_compare)

   {

     header = get_node();

     if(0 == x.root())

     {

         root() = 0;

         leftmost() = header;

         rightmost() = header;

     }

     else

     {

         try{ root() = _copy(x.root(), header); }

         catch()

         {

             release_node(header);

             throw;

         }

         leftmost() = minimum(root());

         rightmost() = maximum(root());

     }

    node_count = x.node_count;

   }

 

   virtual ~Splaytree()

   {

     clear();

     release_node(header);

   }

 

   Splaytree& operator=(const Splaytree& x);

 

public:

   const Compare& key_comp() const { return key_compare; }

   const allocator_type& get_allocator() const { return alloc; }

 

   iterator begin() { return leftmost(); }

   const_iterator begin() const { return leftmost(); }

   iterator end() { return header; }

   const_iterator end() const { return header; }

 

   reverse_iterator rbegin() { return reverse_iterator(end()); }

   const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); }

   reverse_iterator rend() { return reverse_iterator(begin()); }

   const_reverse_iterator rend() const { return const_reverse_iterator(begin()); }

 

   bool empty() const { return 0 == node_count; }

   size_type size() const { return node_count; }

 

   bool find(const value_type& x) const;

   const_reference findmax() const;

   const_reference findmin() const;

 

   iterator insert(const value_type& x);

 

   void remove(const Value& x);

   void remove(iterator position);

   void remove(iterator first, iterator last);

 

   void MakeEmpty();

 

   friend bool operator==(const Splaytree& x, const Splaytree& y)

   {

       return x.size() == y.size() && equal(x.begin(), x.end(), y.begin());

   }

   friend bool operator<(const Splaytree_tree& x, const Splaytree_tree& y)

   {

       return lexicographical_compare(x.begin(), x.end(), y.begin(), y.end());

   }

 

   void swap(Splaytree& t)

   {

       ::swap(header, t.header);

       ::swap(node_count, t.node_count);

       ::swap(key_compare, t.key_compare);

   }

 

   void clear()

   {

       if(node_count != 0)

       {

           erase(root());

           leftmost() = header;

           root() = 0;

           rightmost() = header;

           node_count = 0;

        }

    }

 

}; //end of Splaytree

 

 

 

//Next are definitions of some indispensable functions

 

template <class Value>

inline void _rotate_left(Splaytree_node<Value>* x, Splaytree_node<Value>*& root)

{

   Splaytree_node<Value>* y = x->right;

   x->right = y->left;

   if(y->left) y->left->parent = x;

   y->parent = x->parent;

 

   if(x == root) root = y;

   else if(x == x->parent->left) x->parent->left = y;

   else x->parent->right = y;

   y->left = x;

   x->parent = y;

 }

 

template <class Value>

inline void _rotate_right(Splaytree_node<Value>* x, Splaytree_node<Value>*& root)

{

    Splaytree_node<Value>* y = x->left;

    x->left = y->right;

    if(y->right) y->right->parent = x;

    y->parent = x->parent;

 

    if(x == root) root = y;

    else if(x == x->parent->right) x->parent->right = y;

    else x->parent->left = y;

    y->right = x;

    x->parent = y;

}

 

template <class Key, class Value, class KeyOfValue, class Compare = less<Key>, class  Alloc = allocator<Value> >

inline void _splay(const Vaule& x,Splaytree_node<Value>*& root) //The variable root represents the root, not header, of a tree.

{

    if( root == NULL) return;

    Splaytree_node* header = root->parent;//this variable "header" is the accurate header of the tree

    Splaytree_node* leftTreeMax;

    Splaytree_node* rightTreeMin;

    static Splaytree_node __header(x);//this variable "__header" is an acessorial member

    __header.left = __header.right = NULL;

    leftTreeMax = rightTreeMin = &__header;

 

    while(true)

    {

        if(key_compare( KeyOfValue()(x),key(root))){

            if(key_compare(KeyOfValue()(x), key(root->left))){

                _rotate_left(root,root());

            }

            if(root->left == NULL) break;

            rightTreeMin->left = root;

            rightTreeMin = root;

            root = root->left;

        }

        else if(key_compare(key(root)),KeyOfValue()(x)){

                   if(key_compare(key(root->right)), KeyOfValue()(x)){

                       _rotate_right(root,root());

                   }

                   if(root->right == NULL) break;

                   leftTreeMax->right = root;

                   leftTreeMax = root;

                   root = root->right;

        }

        else break;

    }

 

    leftTreeMin->right = root->left;

    rightTreeMax->left = root->right;

    root->left = __header.right;

    root->right = __header.left;

    root->parent = header;

    header->left = root->minimum(root->left); //leftmost()

    header->right = root->maximum( root->right);  //rightmost()

 

}

 

 

//Next are definitions of some member functions

 

//operator=()

template <class Key, class Value, class KeyOfValue, class Compare, class Alloc>

Splaytree<Key, Value, KeyOfValue, Compare, Alloc>& Splaytree<Key, Value, KeyOfValue, Compare, Alloc>::operator=(const Splaytree<Key, Value, KeyOfValue, Compare, Alloc>& x)

{

    if(this != &x)

    {

        clear();

        node_count = 0;

        key_compare = x.key_compare;

        if(x.root()==NULL){

            root() = NULL;

            leftmost() = header;

            rightmost() = header;

        }

        else{

            root() = clone_node(x.root());

            leftmost() = Splayree_node<Value>::minimum(root());

            rightmost() = Splayree_node<Value>::maximum(root());

            node_count = x.node_count;

        }

   }

   return *this;

}

 

template<class Key,class Value,class KeyOfValue,class compare,class Alloc>

bool Splaytree<Key, Value, KeyOfValue, Compare, Alloc>::find(const Value& x)

{

     _splay(x,root());

     return (value(root()) == x)?true:false;

}

 

template<class Key, class Value, class KeyOfValue, class Compare, class Alloc>

typename Splaytree<Key, Value, KeyOfValue, Compare, Alloc>::const_reference findmax()

{

    Splaytree_node tmp = *this;

    if(!tmp) return NULL;

    tmp = maximum(tmp);

    value_type v = tmp.data;

    _splay(v,root());

    return v;

}

 

template<class Key, class Value, class KeyOfValue, class Compare, class Alloc>

typename Splaytree<Key, Value, KeyOfValue, Compare, Alloc>::const_reference findmin()

{

    Splaytree_node tmp = *this;

    if(!tmp) return NULL;

    tmp = minimum(tmp);

    value_type v = tmp.data;

    _splay(v,root());

    return v;

}

 

template<class Key, class Value, class KeyOfValue, class Compare, class Alloc>

void Splaytree<Key, Value, KeyOfValue, Compare, Alloc>::insert(const Value& x)

{

    Splaytree_node tmp(x);

    if(root()==NULL){

        tmp->left = tmp->right = NULL;

        tmp->parent = header;

        header->parent = tmp;

    }

    else{

        _splay(x,root());

        if(key_compare( KeyOfValue()(x),key(root()))){

            tmp->left = root()->left;

            tmp->right = root();

            root()->left = NULL;

            tmp->parent = header;

            header->parent = tmp;

            leftmost() = Splayree_node<Value>::minimum(root());

            rightmost() = Splayree_node<Value>::maximum(root());

        }

        else if(key_compare( key(root())),KeyOfValue()(x)){

            tmp->right = root()->right;

            tmp->left = root();

            root()->right = NULL;

            tmp->parent = header;

            header->parent = tmp;

            leftmost() = Splayree_node<Value>::minimum(root());

            rightmost() = Splayree_node<Value>::maximum(root());

        }

        else return;

    }

    ++node_count;

}

 

template<class Key,class Value,class KeyOfValue,class compare,class Alloc>

void Splaytree<Key, Value, KeyOfValue, Compare, Alloc>::remove(const Value& x)

{

    _splay(x,root());

    if(KeyOfValue()(x) != key(root())) return;

 

    Splaytree_node tmp;

    if(root()->left == NULL) tmp = root()->right;

    else{

        tmp = root()->left;

        _splay(x,tmp);

        tmp->right = root()->right;

    }

 

    release_node(root());

    root() = tmp;

    header->parent = tmp;

    leftmost() = Splayree_node<Value>::minimum(root());

    rightmost() = Splayree_node<Value>::maximum(root());

    --node_count;

}

 

template<class Key,class Value,class KeyOfValue,class compare,class Alloc>

void Splaytree<Key, Value, KeyOfValue, Compare, Alloc>::remove(iterator position) { remove(*position);}

 

template<class Key,class Value,class KeyOfValue,class compare,class Alloc>

void Splaytree<Key, Value, KeyOfValue, Compare, Alloc>::remove(iterator first,iterator last)

{

    for(const_iterator pos = first;pos!=last;++pos) remove(pos);

}

 

template<class Key,class Value,class KeyOfValue,class compare,class Alloc>

void Splaytree<Key, Value, KeyOfValue, Compare, Alloc>::MakeEmpty()

{

    while(!empty()){

        const_reference v = findmax();

        remove(v);

    }

}

 

#endif // SPLAYTREE_H_

 

 

你可能感兴趣的:(C++,header,tree,iterator,Class,reference)