手打 splay_tree 模板类 支持 find, rank, 前驱后继, iterator
Posted js2xxx
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了手打 splay_tree 模板类 支持 find, rank, 前驱后继, iterator相关的知识,希望对你有一定的参考价值。
- 迭代器中序遍历整棵树,++或--为前驱后继
- 可重复插入,查找,排名(<或<=),删除,大小,相同元素个数
- 功能超全的 stl-like splay 平衡树,摈弃平板电视,还不快收入囊中!
- 插入删除的方式为new/delete,不喜勿喷~
如有错请指正!(支持版本:C++11及以上)
#include <algorithm>
using namespace std;
template<typename T>
class splay_tree_iterator;
template<typename T, typename _Less = less<T>, typename _Equ = equal_to<T>>
class splay_tree
{
public:
friend class splay_tree_iterator<T>;
typedef _Less lesscmp;
typedef _Equ equcmp;
typedef splay_tree_iterator<T> iterator;
splay_tree() : _r(nullptr) { }
iterator root() { return iterator(_r); }
iterator begin()
{
_node *p = _r;
if(!p) return iterator(nullptr);
while(p->s[0]) p = p->s[0];
return iterator(p);
}
iterator end() { iterator k = _end(); return ++k; }
void insert(T o)
{
_node *k = _insert(nullptr, _r, o);
if(k != _r) _splay(k);
}
iterator find(T o)
{
_node *k = _find(_r, o);
if(!k) return end();
return iterator(k);
}
void erase(T o)
{
_node *k = _find(_r, o);
if(!k) return;
_splay(k);
if(k->cnt > 1) { --k->cnt, --k->size; return; }
_node *p = k->_prec();
if(p)
{
_splay(p), p->s[1] = k->s[1];
if(p->s[1]) p->s[1]->f = p;
delete k;
}
else if((p = k->_succ())) _splay(p), delete k;
else delete k, _r = nullptr;
k = nullptr;
if(p) _sync(p);
}
size_t size() { return _r ? _r->size : 0; }
size_t rank(T o, bool equ = false) { return _rank(_r, o, equ); }
private:
lesscmp _cl;
equcmp _ce;
struct _node
{
T v;
int cnt, size;
_node *f, *s[2];
_node * _succ()
{
_node *k = this;
if(!k->s[1])
{
for(; k->f && k->f->s[1] == k; k = k->f);
return k->f;
}
else
{
for(k = k->s[1]; k->s[0]; k = k->s[0]);
return k;
}
}
_node * _prec()
{
_node *k = this;
if(!k->s[0])
{
for(; k->f && k->f->s[0] == k; k = k->f);
return k->f;
}
else
{
for(k = k->s[0]; k->s[1]; k = k->s[1]);
return k;
}
}
} *_r;
inline void _sync(_node *k)
{
k->size = (k->s[0] ? k->s[0]->size : 0) + (k->s[1] ? k->s[1]->size : 0) + k->cnt;
}
inline void _rotate(_node *k)
{
_node *l = k->f, *m = l->f;
bool isr = l->s[1] == k;
if(m) m->s[m->s[1] == l] = k;
k->f = m;
l->s[isr] = k->s[!isr], k->s[!isr] = l, l->f = k;
if(l->s[isr]) l->s[isr]->f = l;
_sync(l), _sync(k);
}
void _splay(_node *k)
{
while(k->f)
{
_node *l {k->f}, *m {l->f};
if(!m) _rotate(k);
else if(m->s[1] == l ^ l->s[1] == k)
_rotate(k), _rotate(k);
else _rotate(l), _rotate(k);
}
_r = k;
}
_node * _insert(_node *f, _node *&k, T o)
{
if(!k) return k = new _node { o, 1, 1, f, nullptr, nullptr };
++k->size;
if(_cl(k->v, o)) return _insert(k, k->s[1], o);
if(!_ce(k->v, o)) return _insert(k, k->s[0], o);
++k->cnt;
return k;
}
_node *_find(_node *k, T o)
{
if(!k) return nullptr;
if(_cl(k->v, o)) return _find(k->s[1], o);
if(!_ce(k->v, o)) return _find(k->s[0], o);
return k;
}
iterator _end()
{
_node *p = _r;
if(!p) return nullptr;
while(p->s[1]) p = p->s[1];
return iterator(p);
}
size_t _rank(_node *k, T o, bool equ)
{
if(!k) return 0;
if(_cl(k->v, o)) return _rank(k->s[1], o, equ) + (k->s[0] ? k->s[0]->size : 0) + k->cnt;
if(!_ce(k->v, o)) return _rank(k->s[0], o, equ);
return (k->s[0] ? k->s[0]->size : 0) + (equ ? k->cnt : 1);
}
};
template<typename T>
class splay_tree_iterator : iterator<bidirectional_iterator_tag, T>
{
public:
friend class splay_tree<T>;
splay_tree_iterator(const splay_tree_iterator<T> &i) : _n(i._n), _p(i._p) { }
splay_tree_iterator &operator++()
{
_p = _n, _n = _n->_succ();
return *this;
}
splay_tree_iterator operator++(int)
{
splay_tree_iterator p(*this);
_p = _n, _n = _n->_succ();
return p;
}
splay_tree_iterator &operator--()
{
if(!_n) _n = _p, _p = nullptr;
else _n = _n->_prec();
return *this;
}
splay_tree_iterator operator--(int)
{
splay_tree_iterator p(*this);
if(!_n) _n = _p, _p = nullptr;
else _n = _n->_prec();
return p;
}
T &operator *() { return _n->v; }
T *operator ->() { return &(_n->v); }
size_t count() { return _n->cnt; }
bool operator != (const splay_tree_iterator<T> &i) { return this->_n != i._n; }
bool operator == (const splay_tree_iterator<T> &i) { return !(*this != i); }
private:
typedef typename splay_tree<T>::_node ptr;
splay_tree_iterator(ptr *p) : _n(p), _p(nullptr) { }
ptr *_n, *_p;
};
以上是关于手打 splay_tree 模板类 支持 find, rank, 前驱后继, iterator的主要内容,如果未能解决你的问题,请参考以下文章
Objective - C 中的KVC(视图便携易懂原创纯手打 定制版)