3 template<
typename t_storage>
20 if (ptr != NULL) ptr->
m_parent =
this;
24 if (ptr != NULL) ptr->
m_parent =
this;
28 (which ? m_right :
m_left) = ptr;
29 if (ptr != NULL) ptr->m_parent =
this;
39 inline t_rawptr
child(
bool which)
const throw() {
return which ? m_right.
get_ptr() : m_left.
get_ptr();}
44 t_rawptr
step(
bool direction)
throw() {
47 t_self* t = walk->
child(direction);
48 if (t != NULL)
return t->
peakchild(!direction);
51 if (t == NULL)
return NULL;
61 if (next == NULL)
return walk;
72 template<
typename t_storage,
typename t_comparator = comparator_default>
92 template<
typename t_item1,
typename t_item2>
93 inline static int compare(
const t_item1 & p_item1,
const t_item2 & p_item2) {
101 return ptr.
is_valid() ? 1+ptr->m_depth : 0;
105 ptr->m_depth =
pfc::max_t(calc_depth(ptr->m_left), calc_depth(ptr->m_right));
109 PFC_ASSERT(ptr->m_depth ==
pfc::max_t(calc_depth(ptr->m_left),calc_depth(ptr->m_right)) );
114 if (ptr==0)
return 0;
115 else return calc_depth(ptr->m_right) - calc_depth(ptr->m_left);
119 if (is_ptr_valid(p_base->m_left)) {
120 t_nodeptr ret = extract_left_leaf(p_base->m_left);
121 recalc_depth(p_base);
125 t_nodeptr node = p_base;
126 p_base = node->m_right;
127 if (p_base.
is_valid()) p_base->m_parent = node->m_parent;
130 node->m_parent = NULL;
136 if (is_ptr_valid(p_base->m_right)) {
137 t_nodeptr ret = extract_right_leaf(p_base->m_right);
138 recalc_depth(p_base);
142 t_nodeptr node = p_base;
143 p_base = node->m_left;
144 if (p_base.
is_valid()) p_base->m_parent = node->m_parent;
147 node->m_parent = NULL;
153 t_nodeptr oldval = p_node;
155 p_node = p_node->m_right;
156 if (p_node.
is_valid()) p_node->m_parent = oldval->m_parent;
157 }
else if (p_node->m_right.
is_empty()) {
158 p_node = p_node->m_left;
159 if (p_node.
is_valid()) p_node->m_parent = oldval->m_parent;
161 t_nodeptr swap = extract_left_leaf(p_node->m_right);
163 swap->link_left(oldval->m_left.
get_ptr());
164 swap->link_right(oldval->m_right.
get_ptr());
165 swap->m_parent = oldval->m_parent;
172 template<
typename t_nodewalk,
typename t_callback>
174 if (is_ptr_valid(p_node)) {
175 __enum_items_recur<t_nodewalk>(p_node->m_left.get_ptr(),p_callback);
176 p_callback (p_node->m_content);
177 __enum_items_recur<t_nodewalk>(p_node->m_right.get_ptr(),p_callback);
180 template<
typename t_search>
181 static t_node *
g_find_or_add_node(t_nodeptr & p_base,t_node * parent,t_search
const & p_search,
bool & p_new)
184 p_base =
new t_node(p_search);
185 p_base->m_parent = parent;
190 PFC_ASSERT( p_base->m_parent == parent );
192 int result =
compare(p_base->m_content,p_search);
194 t_node * ret = g_find_or_add_node<t_search>(p_base->m_left,p_base.
get_ptr(),p_search,p_new);
196 recalc_depth(p_base);
200 }
else if (result < 0) {
201 t_node * ret = g_find_or_add_node<t_search>(p_base->m_right,p_base.
get_ptr(),p_search,p_new);
203 recalc_depth(p_base);
215 template<
typename t_search>
216 static t_storage *
g_find_or_add(t_nodeptr & p_base,t_node * parent,t_search
const & p_search,
bool & p_new) {
217 return &g_find_or_add_node(p_base,parent,p_search,p_new)->m_content;
222 t_nodeptr newroot ( oldroot->m_right );
223 oldroot->link_child(
true, newroot->m_left.
get_ptr());
224 newroot->m_left = oldroot;
225 newroot->m_parent = oldroot->m_parent;
226 oldroot->m_parent = newroot.
get_ptr();
227 recalc_depth(oldroot);
228 recalc_depth(newroot);
233 t_nodeptr newroot ( oldroot->m_left );
234 oldroot->link_child(
false, newroot->m_right.
get_ptr());
235 newroot->m_right = oldroot;
236 newroot->m_parent = oldroot->m_parent;
237 oldroot->m_parent = newroot.
get_ptr();
238 recalc_depth(oldroot);
239 recalc_depth(newroot);
244 t_ssize balance = test_depth(p_node);
247 if (test_depth(p_node->m_right) < 0) {
248 g_rotate_left(p_node->m_right);
250 g_rotate_right(p_node);
251 }
else if (balance < -1) {
253 if (test_depth(p_node->m_left) > 0) {
254 g_rotate_right(p_node->m_left);
256 g_rotate_left(p_node);
261 template<
typename t_search>
262 static bool g_remove(t_nodeptr & p_node,t_search
const & p_search) {
263 if (p_node.
is_empty())
return false;
265 int result =
compare(p_node->m_content,p_search);
267 remove_internal(p_node);
268 if (is_ptr_valid(p_node)) {
269 recalc_depth(p_node);
274 if (g_remove<t_search>(result > 0 ? p_node->m_left : p_node->m_right,p_search)) {
275 recalc_depth(p_node);
285 #if 0 //def _DEBUG//SLOW! 286 if (is_ptr_valid(p_node)) {
289 assert_children(p_node);
290 t_ssize delta = test_depth(p_node);
291 PFC_ASSERT(delta >= -1 && delta <= 1);
294 PFC_ASSERT( p_node.
get_ptr() == p_node->m_left->m_parent );
297 PFC_ASSERT( p_node.
get_ptr() == p_node->m_right->m_parent );
300 if (is_ptr_valid(p_node->m_parent)) {
301 PFC_ASSERT(p_node == p_node->m_parent->m_left || p_node == p_node->m_parent->m_right);
309 if (is_ptr_valid(p_node)) {
310 return 1 + calc_count(p_node->m_left.get_ptr()) + calc_count(p_node->m_right.get_ptr());
316 template<
typename t_param>
318 t_node* ptr = m_root.
get_ptr();
319 while(is_ptr_valid(ptr)) {
320 int result =
compare(ptr->m_content,p_item);
323 else return &ptr->m_content;
328 template<
typename t_param>
330 t_node* ptr = m_root.
get_ptr();
331 while(is_ptr_valid(ptr)) {
332 int result =
compare(ptr->m_content,p_item);
340 template<
bool inclusive,
bool above,
typename t_search> t_storage *
__find_nearest(
const t_search & p_search)
const {
341 t_node * ptr = m_root.
get_ptr();
342 t_storage * found = NULL;
343 while(is_ptr_valid(ptr)) {
344 int result =
compare(ptr->m_content,p_search);
345 if (above) result = -result;
346 if (inclusive && result == 0) {
348 found = &ptr->m_content;
350 }
else if (result < 0) {
352 found = &ptr->m_content;
353 ptr = ptr->
child(!above);
356 ptr = ptr->
child(above);
364 const t_self &
operator=(
const t_self & p_other) {__copy(p_other);
return *
this;}
365 avltree_t(
const t_self & p_other) : m_root(NULL) {
try{__copy(p_other);}
catch(...) {remove_all();
throw;}}
371 template<
bool inclusive,
bool above,
typename t_search>
const t_storage *
find_nearest_item(
const t_search & p_search)
const {
372 return __find_nearest<inclusive,above>(p_search);
375 template<
bool inclusive,
bool above,
typename t_search> t_storage *
find_nearest_item(
const t_search & p_search) {
376 return __find_nearest<inclusive,above>(p_search);
379 template<
typename t_param>
382 return add_item_ex(p_item,dummy);
385 template<
typename t_param>
386 t_self &
operator+=(
const t_param & p_item) {add_item(p_item);
return *
this;}
388 template<
typename t_param>
389 t_self &
operator-=(
const t_param & p_item) {remove_item(p_item);
return *
this;}
392 template<
typename t_param>
395 g_find_or_add(m_root,NULL,item,isNew);
399 template<
typename t_param>
401 t_storage * ret = g_find_or_add(m_root,NULL,p_item,p_isnew);
406 template<
typename t_param>
409 t_storage & found = add_item_ex(p_item,isnew);
410 if (isnew) found = p_item;
413 template<
typename t_param>
414 const t_storage *
find_item_ptr(t_param
const & p_item)
const {
return _find_item_ptr(p_item);}
417 template<
typename t_param>
418 t_storage *
find_item_ptr(t_param
const & p_item) {
return _find_item_ptr(p_item); }
420 template<
typename t_param> const_iterator
find(t_param
const & item)
const {
return _find_node_ptr(item);}
423 template<
typename t_param> iterator
find(t_param
const & item) {
return _find_node_ptr(item);}
426 template<
typename t_param>
428 return find_item_ptr(p_item) != NULL;
432 template<
typename t_param>
433 bool have_item(
const t_param & p_item)
const {
return contains(p_item);}
436 _unlink_recur(m_root);
440 bool remove(const_iterator
const& iter) {
441 PFC_ASSERT(iter.is_valid());
442 return remove_item(*iter);
446 template<
typename t_param>
448 bool ret = g_remove<t_param>(m_root,p_item);
454 return calc_count(m_root.
get_ptr());
457 template<
typename t_callback>
459 __enum_items_recur<const t_node>(m_root.
get_ptr(),p_callback);
464 template<
typename t_callback>
467 template<
typename t_param> iterator
insert(
const t_param & p_item) {
469 t_node * ret = g_find_or_add_node(m_root,NULL,p_item,isNew);
475 template<
typename t_param> t_storage &
add(
const t_param & p_item) {
return add_item(p_item);}
476 template<
typename t_param> t_storage &
add_ex(
const t_param & p_item,
bool & p_isnew) {
return add_item_ex(p_item,p_isnew);}
477 template<
typename t_param>
const t_storage *
find_ptr(t_param
const & p_item)
const {
return find_item_ptr(p_item);}
478 template<
typename t_param> t_storage *
find_ptr(t_param
const & p_item) {
return find_item_ptr(p_item);}
479 template<
typename t_param>
bool exists(t_param
const & p_item)
const {
return have_item(p_item);}
485 const_iterator
first()
const throw() {
return _firstlast(
false);}
486 const_iterator
last()
const throw() {
return _firstlast(
true);}
492 template<
typename t_param>
bool get_first(t_param & p_item)
const throw() {
493 const_iterator iter = first();
498 template<
typename t_param>
bool get_last(t_param & p_item)
const throw() {
499 const_iterator iter = last();
505 static bool equals(
const t_self & v1,
const t_self & v2) {
514 _unlink_recur(node->m_left);
515 _unlink_recur(node->m_right);
523 if (next == NULL)
return walk;
529 if (p_source == NULL) {
532 t_nodeptr newnode =
new t_node(p_source->m_content);
533 newnode->m_depth = p_source->
m_depth;
536 newnode->m_parent = parent;
549 template<
typename t_storage,
typename t_comparator>
bool add_item_check(t_param const &item)
Returns true when the list has been altered, false when the item was already present before...
Base class for list nodes. Implemented by list implementers.
bool exists(t_param const &p_item) const
t_storage & add(const t_param &p_item)
bool get_first(t_param &p_item) const
refcounted_object_ptr_t< t_self > t_ptr
static bool listEquals(const t_list1 &p_list1, const t_list2 &p_list2)
void _enumerate_var(t_callback &p_callback)
Allows callback to modify the tree content. Unsafe! Caller must not modify items in a way that change...
bool operator!=(const t_self &other) const
t_node * _firstlast(bool which) const
void copy_list_enumerated(t_receiver &p_receiver, const t_giver &p_giver)
const t_storage * find_nearest_item(const t_search &p_search) const
void link_child(bool which, t_self *ptr)
static bool is_ptr_valid(t_nodeptr const &p)
refcounted_object_ptr_t< t_node > t_nodeptr
t_rawptr child(bool which) const
void set_item(const t_param &p_item)
int compare(t1 const &p1, t2 const &p2)
t_storage * __find_nearest(const t_search &p_search) const
const t_self & operator=(const t_self &p_other)
iterator _first_var()
Unsafe! Caller must not modify items in a way that changes sort order!
static void recalc_depth(t_nodeptr const &ptr)
static bool equals(const t_self &v1, const t_self &v2)
t_node * _find_node_ptr(t_param const &p_item) const
void __copy(const t_self &p_other)
static t_size calc_count(const t_node *p_node)
static bool g_remove(t_nodeptr &p_node, t_search const &p_search)
t_self * walk(bool forward)
static void selftest(t_nodeptr const &p_node)
static t_size calc_depth(const t_nodeptr &ptr)
t_self & operator+=(const t_param &p_item)
bool have_item(const t_param &p_item) const
Same as contains().
static void remove_internal(t_nodeptr &p_node)
t_storage & add_ex(const t_param &p_item, bool &p_isnew)
_avltree_node< t_storage > t_self
t_node::t_rawptr t_noderawptr
t_storage * find_ptr(t_param const &p_item)
pfc::iterator< t_storage > iterator
static void g_rebalance(t_nodeptr &p_node)
t_rawptr peakchild(bool direction)
t_storage * _find_item_ptr(t_param const &p_item) const
iterator _last_var()
Unsafe! Caller must not modify items in a way that changes sort order!
const_iterator find(t_param const &item) const
const_iterator first() const
void enumerate(t_callback &p_callback) const
static void __enum_items_recur(t_nodewalk *p_node, t_callback &p_callback)
iterator find(t_param const &item)
Unsafe! Caller must not modify items in a way that changes sort order!
avltree_t(const t_self &p_other)
static t_ssize test_depth(t_nodeptr const &ptr)
static t_nodeptr __copy_recur(t_node *p_source, t_node *parent)
_avltree_node< t_storage > t_node
avltree_t(const t_other &p_other)
pfc::const_iterator< t_storage > const_iterator
static t_storage * g_find_or_add(t_nodeptr &p_base, t_node *parent, t_search const &p_search, bool &p_new)
bool which_child(const t_self *ptr) const
void link_left(t_self *ptr)
static void g_rotate_left(t_nodeptr &oldroot)
t_self & operator-=(const t_param &p_item)
iterator insert(const t_param &p_item)
_avltree_node(t_param const ¶m)
static void assert_children(t_nodeptr ptr)
t_storage & add_item(t_param const &p_item)
t_storage & add_item_ex(t_param const &p_item, bool &p_isnew)
pfc::sized_int_t< sizeof(size_t) >::t_signed t_ssize
static int compare(const t_item1 &p_item1, const t_item2 &p_item2)
const t_storage * find_ptr(t_param const &p_item) const
static void _unlink_recur(t_nodeptr &node)
avltree_t< t_storage, t_comparator > t_self
t_rawptr step(bool direction)
static t_nodeptr extract_left_leaf(t_nodeptr &p_base)
const t_storage * find_item_ptr(t_param const &p_item) const
static t_nodeptr extract_right_leaf(t_nodeptr &p_base)
bool operator==(const t_self &other) const
t_storage * find_item_ptr(t_param const &p_item)
Unsafe! Caller must not modify items in a way that changes sort order!
static void g_rotate_right(t_nodeptr &oldroot)
static bool is_ptr_valid(t_node const *p)
T max_t(const T &item1, const T &item2)
_list_node< t_storage > t_node
bool get_last(t_param &p_item) const
const_iterator last() const
static t_node * g_find_or_add_node(t_nodeptr &p_base, t_node *parent, t_search const &p_search, bool &p_new)
t_storage * find_nearest_item(const t_search &p_search)
void link_right(t_self *ptr)
const t_self & operator=(const t_other &p_other)
bool contains(const t_param &p_item) const
bool remove_item(t_param const &p_item)
bool equals(const t1 &v1, const t2 &v2)