#![allow(rustdoc::redundant_explicit_links)]
#![cfg_attr(docsrs, feature(doc_cfg))]
#![cfg_attr(docsrs, allow(unused_attributes))]
#![cfg_attr(not(feature = "std"), no_std)]
extern crate alloc;
#[cfg(any(feature = "std", test))]
extern crate std;
mod entry;
mod iter;
pub use entry::*;
pub use iter::*;
#[cfg(test)]
mod tests;
use alloc::collections::vec_deque::VecDeque;
use alloc::vec::Vec;
use core::marker::PhantomData;
use core::{
borrow::Borrow,
cmp::{Ordering, PartialEq},
fmt, mem,
ops::Deref,
ptr::{NonNull, null_mut},
};
use pointers::{CloneablePointer, Pointer};
pub unsafe trait AvlItem<Tag>: Sized {
fn get_node(&self) -> &mut AvlNode<Self, Tag>;
}
#[macro_export]
macro_rules! impl_ord_with_borrow {
($cls: ty, $key_type: ty) => {
impl PartialOrd for $cls {
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
Some(Ord::cmp(self, other))
}
}
impl PartialEq for $cls {
fn eq(&self, other: &Self) -> bool {
Borrow::<$key_type>::borrow(self) == Borrow::<$key_type>::borrow(other)
}
}
impl Eq for $cls {}
impl Ord for $cls {
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
Borrow::<$key_type>::borrow(self).cmp(Borrow::<$key_type>::borrow(other))
}
}
};
}
#[macro_export(local_inner_macros)]
macro_rules! trace_log {
($($arg:tt)+)=>{
#[cfg(feature="trace_log")]
{
log::debug!($($arg)+);
}
};
}
pub(crate) const DIR_LEFT: Dir = Dir(false);
pub(crate) const DIR_RIGHT: Dir = Dir(true);
#[derive(PartialEq, Debug, Copy, Clone)]
pub(crate) struct Dir(bool);
impl Dir {
#[inline(always)]
const fn to_usize(&self) -> usize {
self.0 as usize
}
#[inline(always)]
const fn reverse(&self) -> Self {
Self(!self.0)
}
#[inline(always)]
fn to_balance(&self) -> i8 {
if *self == DIR_LEFT { -1 } else { 1 }
}
}
impl From<i8> for Dir {
#[inline(always)]
fn from(i: i8) -> Self {
Self(i != 0)
}
}
impl From<bool> for Dir {
#[inline(always)]
fn from(i: bool) -> Self {
Self(i)
}
}
pub struct AvlNode<T: AvlItem<Tag>, Tag> {
pub parent: *mut T,
pub children: [*mut T; 2],
pub balance: i8,
_phan: PhantomData<fn(&Tag)>,
}
unsafe impl<T: AvlItem<Tag> + Send, Tag> Send for AvlNode<T, Tag> {}
impl<T: AvlItem<Tag>, Tag> AvlNode<T, Tag> {
#[inline(always)]
pub fn detach(&mut self) {
self.children = [null_mut(), null_mut()];
self.parent = null_mut();
self.balance = 0;
}
#[inline(always)]
fn get_child(&self, dir: Dir) -> *mut T {
unsafe { *self.children.get_unchecked(dir.to_usize()) }
}
#[inline(always)]
fn set_child(&mut self, dir: Dir, child: *mut T) {
self.children[dir.to_usize()] = child;
}
#[inline(always)]
fn left(&self) -> *mut T {
self.children[0]
}
#[inline(always)]
fn right(&self) -> *mut T {
self.children[1]
}
#[inline(always)]
fn set_child2<P: Pointer<Target = T>>(
&mut self, dir: Dir, child: *mut P::Target, parent: *mut P::Target,
) {
if !child.is_null() {
unsafe { (*child).get_node().parent = parent };
}
self.set_child(dir, child);
}
#[inline(always)]
fn get_parent(&self) -> *mut T {
self.parent
}
#[inline(always)]
fn _child_direction(&self, child_p: *mut T) -> Dir {
let is_right = self.children[1] == child_p;
#[cfg(debug_assertions)]
{
if !is_right {
debug_assert!(self.children[0] == child_p, "{self:?} find child {child_p:p}");
}
}
is_right.into()
}
#[inline(always)]
fn child_direction(parent: *mut T, child_p: *mut T) -> Dir {
if !parent.is_null() {
unsafe { (*parent).get_node() }._child_direction(child_p)
} else {
DIR_LEFT
}
}
#[inline(always)]
fn parent_direction(node: *mut T) -> Dir {
let parent = unsafe { (*node).get_node() }.get_parent();
Self::child_direction(parent, node)
}
#[inline(always)]
pub fn swap(&mut self, other: &mut AvlNode<T, Tag>) {
mem::swap(self, other);
}
}
impl<T: AvlItem<Tag>, Tag> Default for AvlNode<T, Tag> {
fn default() -> Self {
Self {
children: [null_mut(), null_mut()],
parent: null_mut(),
balance: 0,
_phan: Default::default(),
}
}
}
#[allow(unused_must_use)]
impl<T: AvlItem<Tag>, Tag> fmt::Debug for AvlNode<T, Tag> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "( {:p} parent: {:p} balance: {}", self, self.parent, self.balance)?;
if !self.left().is_null() {
write!(f, " left: {:p}", self.left())?;
} else {
write!(f, " left: none")?;
}
if !self.right().is_null() {
write!(f, " right: {:p}", self.right())?;
} else {
write!(f, " right: none")?;
}
write!(f, ")")
}
}
pub struct AvlTree<P, Tag>
where
P: Pointer,
P::Target: AvlItem<Tag>,
{
root: *mut P::Target,
count: usize,
_phan: PhantomData<fn(P, &Tag)>,
}
impl<P, Tag> Default for AvlTree<P, Tag>
where
P: Pointer + Send,
P::Target: AvlItem<Tag>,
{
#[inline(always)]
fn default() -> Self {
Self::new()
}
}
unsafe impl<P, Tag> Send for AvlTree<P, Tag>
where
P: Pointer + Send,
P::Target: AvlItem<Tag>,
{
}
unsafe impl<P, Tag> Sync for AvlTree<P, Tag>
where
P: Pointer + Send,
P::Target: AvlItem<Tag>,
{
}
impl<P, Tag> fmt::Debug for AvlTree<P, Tag>
where
P: Pointer,
P::Target: AvlItem<Tag> + fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let _ = write!(f, "AvlTree{{");
if self.count > 0 {
let mut iter = self.iter();
loop {
let node = iter.next().unwrap();
let _ = write!(f, "{:?}", node.as_ref().as_ref());
if iter.len() > 0 {
let _ = write!(f, ", ");
} else {
break;
}
}
}
write!(f, "}}")
}
}
impl<P, Tag> AvlTree<P, Tag>
where
P: Pointer,
P::Target: AvlItem<Tag>,
{
#[inline]
pub fn new() -> Self {
AvlTree { count: 0, root: null_mut(), _phan: Default::default() }
}
#[inline]
pub fn is_empty(&self) -> bool {
self.count == 0
}
#[inline]
pub fn len(&self) -> usize {
self.count
}
#[inline]
pub fn add(&mut self, node: P) -> Result<(), P>
where
P::Target: Ord,
{
if !self.root.is_null() {
let mut parent = self.root;
unsafe {
loop {
let dir = match node.as_ref().cmp((&*parent).as_ref()) {
Ordering::Greater => DIR_RIGHT,
Ordering::Less => DIR_LEFT,
Ordering::Equal => return Err(node),
};
let child = (*parent).get_node().get_child(dir);
if !child.is_null() {
parent = child;
} else {
self._insert(node.into_raw() as *mut P::Target, parent, dir);
return Ok(());
}
}
}
} else {
debug_assert_eq!(self.count, 0);
self.root = node.into_raw() as *mut P::Target;
self.count = 1;
Ok(())
}
}
#[inline]
pub fn remove_by_key<K>(&mut self, key: &K) -> Option<P>
where
P::Target: Borrow<K>,
K: Ord,
{
let _cmp = |_key: &&K, node: &P::Target| -> Ordering { _key.cmp(&node.borrow()) };
if let Entry::Occupied(ent) = self.entry_with::<&K, _>(key, _cmp) {
Some(ent.remove())
} else {
None
}
}
#[inline]
pub fn remove(&mut self, node: &P)
where
P::Target: Ord,
{
let _cmp = |_cur: &&P::Target, node: &P::Target| -> Ordering { _cur.cmp(&node.borrow()) };
if let Entry::Occupied(ent) = self.entry_with::<&P::Target, _>(node.as_ref(), _cmp) {
ent.remove();
}
}
#[inline]
pub fn entry<'a, K>(&'a mut self, key: K) -> Entry<'a, P, Tag, K>
where
P::Target: Borrow<K>,
K: Ord,
{
self.entry_with(key, |_key: &K, node: &P::Target| _key.cmp(node.borrow()))
}
#[inline]
pub fn entry_with<'a, K, F>(&'a mut self, key: K, cmp_f: F) -> Entry<'a, P, Tag, K>
where
F: Fn(&K, &P::Target) -> Ordering,
{
if !self.root.is_null() {
let mut parent = self.root;
loop {
let dir = match cmp_f(&key, unsafe { &*parent }.as_ref()) {
Ordering::Greater => DIR_RIGHT,
Ordering::Less => DIR_LEFT,
Ordering::Equal => {
return Entry::Occupied(OccupiedEntry {
node: unsafe { NonNull::new_unchecked(parent) },
tree: self,
});
}
};
let child = unsafe { (*parent).get_node() }.get_child(dir);
if !child.is_null() {
parent = child;
} else {
return Entry::Vacant(VacantEntry {
node: parent,
direction: dir,
tree: self,
key,
});
}
}
} else {
Entry::Vacant(VacantEntry { node: null_mut(), direction: DIR_RIGHT, tree: self, key })
}
}
#[inline]
pub fn get<'a, K>(&'a self, key: &K) -> Option<AvlNodeRef<'a, P>>
where
P::Target: Borrow<K>,
K: Ord,
{
self.get_with(|node| key.cmp(node.borrow()))
}
pub fn get_with<'a, F>(&'a self, cmp_f: F) -> Option<AvlNodeRef<'a, P>>
where
F: Fn(&P::Target) -> Ordering,
{
if !self.root.is_null() {
let mut node = self.root;
loop {
let dir = match cmp_f(unsafe { &*node }.as_ref()) {
Ordering::Greater => DIR_RIGHT,
Ordering::Less => DIR_LEFT,
Ordering::Equal => return Some(AvlNodeRef::new(node)),
};
let child = unsafe { (*node).get_node() }.get_child(dir);
if !child.is_null() {
node = child;
} else {
return None;
}
}
} else {
None
}
}
#[allow(clippy::not_unsafe_ptr_arg_deref)]
#[inline]
pub(crate) fn _insert(
&mut self,
new_ptr: *mut P::Target,
parent: *mut P::Target, mut which_child: Dir,
) {
if !parent.is_null() {
let mut new_balance: i8;
unsafe { (*new_ptr).get_node() }.parent = parent;
let parent_node = unsafe { (*parent).get_node() };
parent_node.set_child(which_child, new_ptr);
self.count += 1;
let mut data: *mut P::Target = parent;
loop {
let node = unsafe { (*data).get_node() };
let old_balance = node.balance;
new_balance = old_balance + which_child.to_balance();
if new_balance == 0 {
node.balance = 0;
return;
}
if old_balance != 0 {
break;
}
node.balance = new_balance;
let parent_ptr = node.get_parent();
if parent_ptr.is_null() {
return;
}
which_child = unsafe { (*parent_ptr).get_node() }._child_direction(data);
data = parent_ptr;
}
self.rotate(data, new_balance);
} else {
debug_assert_eq!(self.count, 0);
self.root = new_ptr;
self.count += 1;
}
}
unsafe fn _insert_here(
&mut self, new_ptr: *mut P::Target, here: NonNull<P::Target>, direction: Dir,
) {
crate::trace_log!("_insert_here {new_ptr:p} here {here:p} dir {direction:?}");
let mut dir_child = direction;
unsafe {
let child = here.as_ref().get_node().get_child(dir_child);
let parent;
if child.is_null() {
crate::trace_log!("direct at here {here:p}");
parent = here;
} else {
dir_child = dir_child.reverse();
parent = Self::bottom_child(NonNull::new_unchecked(child), dir_child);
crate::trace_log!("find bottom {parent:p}");
}
self._insert(new_ptr, parent.as_ptr(), dir_child);
}
}
#[inline]
fn rotate(&mut self, data: *mut P::Target, balance: i8) -> bool {
let dir: Dir = (balance >= 0).into();
let node = unsafe { (*data).get_node() };
crate::trace_log!("rotate: {data:p} {node:?} balance: {balance}");
let parent = node.get_parent();
let dir_inverse = dir.reverse();
let left_heavy = balance >> 1;
let right_heavy = -left_heavy;
let child = node.get_child(dir);
let child_node = unsafe { (*child).get_node() };
let mut child_balance = child_node.balance;
let which_child = AvlNode::<P::Target, Tag>::child_direction(parent, data);
crate::trace_log!("rotate: choose {child_node:?} dir {dir:?}");
if child_balance != right_heavy {
child_balance += right_heavy;
let c_right = child_node.get_child(dir_inverse);
node.set_child2::<P>(dir, c_right, data);
node.balance = -child_balance;
node.parent = child;
child_node.set_child(dir_inverse, data);
child_node.balance = child_balance;
if !parent.is_null() {
child_node.parent = parent;
unsafe { (*parent).get_node() }.set_child(which_child, child);
} else {
child_node.parent = null_mut();
self.root = child;
}
return child_balance == 0;
}
let g_child = child_node.get_child(dir_inverse);
let g_child_node = unsafe { (*g_child).get_node() };
let g_left = g_child_node.get_child(dir);
let g_right = g_child_node.get_child(dir_inverse);
node.set_child2::<P>(dir, g_right, data);
child_node.set_child2::<P>(dir_inverse, g_left, child);
let g_child_balance = g_child_node.balance;
if g_child_balance == right_heavy {
child_node.balance = left_heavy;
} else {
child_node.balance = 0;
}
child_node.parent = g_child;
g_child_node.set_child(dir, child);
if g_child_balance == left_heavy {
node.balance = right_heavy;
} else {
node.balance = 0;
}
g_child_node.balance = 0;
node.parent = g_child;
g_child_node.set_child(dir_inverse, data);
if !parent.is_null() {
g_child_node.parent = parent;
unsafe { (*parent).get_node() }.set_child(which_child, g_child);
} else {
g_child_node.parent = null_mut();
self.root = g_child;
}
true
}
pub(crate) unsafe fn _remove(&mut self, del: *mut P::Target) {
let del_node = unsafe { (*del).get_node() };
let old_parent = del_node.get_parent();
let mut del_dir = AvlNode::<P::Target, Tag>::child_direction(old_parent, del);
let mut imm_parent = old_parent;
let del_left = del_node.left();
let del_right = del_node.right();
if del_left.is_null() || del_right.is_null() {
let dir_child = (!del_right.is_null()).into();
let imm_child = del_node.get_child(dir_child);
crate::trace_log!("del {del_node:?} direct with dir {dir_child:?} child {imm_child:p}",);
if !imm_child.is_null() {
unsafe { (*imm_child).get_node() }.parent = imm_parent;
}
if !imm_parent.is_null() {
unsafe { (*imm_parent).get_node() }.set_child(del_dir, imm_child);
} else {
self.root = imm_child;
}
} else {
let dir_child: Dir = (del_node.balance == 1).into();
let dir_child_inverse: Dir = dir_child.reverse();
let child_temp = del_node.get_child(dir_child);
let child = Self::bottom_child(
unsafe { NonNull::new_unchecked(child_temp) },
dir_child_inverse,
)
.as_ptr();
if !old_parent.is_null() {
unsafe { (*old_parent).get_node() }.set_child(del_dir, child);
} else {
self.root = child;
}
if child != child_temp {
let parent_dir_child = AvlNode::<P::Target, Tag>::parent_direction(child);
let child_node = unsafe { (*child).get_node() };
imm_parent = child_node.get_parent();
crate::trace_log!(
"del {:?} swap with indirect child dir {:?} {:?} which parent_dir: {:?}",
del_node,
dir_child,
child_node,
parent_dir_child
);
debug_assert!(child_node.get_child(dir_child_inverse).is_null());
child_node.swap(del_node);
unsafe { (*del_left).get_node() }.parent = child;
unsafe { (*del_right).get_node() }.parent = child;
del_dir = parent_dir_child;
let imm_child = del_node.get_child(dir_child);
if !imm_child.is_null() {
unsafe { (*imm_child).get_node() }.parent = imm_parent;
}
debug_assert!(!imm_parent.is_null());
unsafe { (*imm_parent).get_node() }.set_child(del_dir, imm_child);
debug_assert!(del_node.get_child(dir_child_inverse).is_null());
} else {
let child_node = unsafe { (*child).get_node() };
crate::trace_log!(
"del {:?} swap with direct child {:?} at {:?}",
del_node,
child_node,
dir_child
);
child_node.parent = old_parent;
child_node.balance = del_node.balance;
let other_child = del_node.get_child(dir_child_inverse);
debug_assert!(!other_child.is_null());
child_node.set_child(dir_child_inverse, other_child);
unsafe { (*other_child).get_node() }.parent = child;
del_dir = dir_child;
imm_parent = child;
}
}
self.count -= 1;
del_node.detach();
if !imm_parent.is_null() {
self._post_remove(imm_parent, del_dir);
}
}
#[inline]
fn _post_remove(&mut self, parent: *mut P::Target, mut which_child: Dir) {
debug_assert!(!parent.is_null());
let mut node_data: *mut P::Target = parent;
loop {
let node = unsafe { (*node_data).get_node() };
let balance_delta = -which_child.to_balance();
let old_balance = node.balance;
if old_balance == 0 {
crate::trace_log!("{node:?} update balance dir{which_child:?} {balance_delta}");
node.balance = balance_delta;
break;
}
let new_balance = old_balance + balance_delta;
let parent = node.get_parent();
let next_which_child = AvlNode::<P::Target, Tag>::child_direction(parent, node_data);
if new_balance == 0 {
crate::trace_log!("{node:?} update balance dir{which_child:?} 0");
node.balance = 0;
} else if !self.rotate(node_data, new_balance) {
break;
}
if !parent.is_null() {
crate::trace_log!("move up {parent:?} for dir{which_child:?}");
node_data = parent;
which_child = next_which_child;
continue;
}
break;
}
#[cfg(debug_assertions)]
{
if self.root.is_null() && self.count > 0 {
panic!("AvlTree {} nodes left after remove but tree.root == nil", self.count);
}
}
}
#[inline(always)]
fn bottom_child(mut data: NonNull<P::Target>, dir: Dir) -> NonNull<P::Target> {
loop {
unsafe {
let child = data.as_ref().get_node().get_child(dir);
if !child.is_null() {
data = NonNull::new_unchecked(child);
} else {
return data;
}
}
}
}
#[inline]
pub fn iter(&self) -> AvlIter<'_, P, Tag> {
let first_p = if !self.root.is_null() {
Some(Self::bottom_child(unsafe { NonNull::new_unchecked(self.root) }, DIR_LEFT))
} else {
None
};
AvlIter::new(self, first_p, DIR_RIGHT)
}
#[inline]
pub fn iter_rev(&self) -> AvlIter<'_, P, Tag> {
let last_p = if !self.root.is_null() {
Some(Self::bottom_child(unsafe { NonNull::new_unchecked(self.root) }, DIR_RIGHT))
} else {
None
};
AvlIter::new(self, last_p, DIR_LEFT)
}
#[inline]
pub fn into_iter_rev(self) -> AvlIntoIter<P, Tag> {
let node = self.root;
core::mem::forget(self);
AvlIntoIter::new(node, DIR_RIGHT)
}
#[inline]
pub fn prev<'a>(&'a self, data: &'a P::Target) -> Option<AvlNodeRef<'a, P>> {
Self::_walk_dir(data.into(), DIR_LEFT).map(|p| AvlNodeRef::new(p.as_ptr()))
}
#[inline]
pub fn next<'a>(&'a self, data: &'a P::Target) -> Option<AvlNodeRef<'a, P>> {
Self::_walk_dir(data.into(), DIR_RIGHT).map(|p| AvlNodeRef::new(p.as_ptr()))
}
fn _walk_dir(mut data_ptr: NonNull<P::Target>, dir: Dir) -> Option<NonNull<P::Target>> {
let dir_inverse = dir.reverse();
let node = unsafe { data_ptr.as_ref().get_node() };
let temp = node.get_child(dir);
if !temp.is_null() {
unsafe { Some(Self::bottom_child(NonNull::new_unchecked(temp), dir_inverse)) }
} else {
let mut parent = node.parent;
while !parent.is_null() {
let pdir = AvlNode::<P::Target, Tag>::child_direction(parent, data_ptr.as_ptr());
if pdir == dir_inverse {
return Some(unsafe { NonNull::new_unchecked(parent) });
}
let data_ptr_raw = parent;
unsafe {
parent = (*parent).get_node().parent;
data_ptr = NonNull::new_unchecked(data_ptr_raw);
}
}
debug_assert!(parent.is_null());
None
}
}
#[inline]
pub fn first<'a>(&'a self) -> Option<AvlNodeRef<'a, P>> {
if !self.root.is_null() {
let p = Self::bottom_child(unsafe { NonNull::new_unchecked(self.root) }, DIR_LEFT);
Some(AvlNodeRef::<'a, P>::new(p.as_ptr()))
} else {
None
}
}
#[inline]
pub fn last<'a>(&'a self) -> Option<AvlNodeRef<'a, P>> {
if !self.root.is_null() {
let p = Self::bottom_child(unsafe { NonNull::new_unchecked(self.root) }, DIR_RIGHT);
Some(AvlNodeRef::<'a, P>::new(p.as_ptr()))
} else {
None
}
}
#[inline]
pub fn first_entry<'a>(&'a mut self) -> Entry<'a, P, Tag, First> {
if !self.root.is_null() {
let p = Self::bottom_child(unsafe { NonNull::new_unchecked(self.root) }, DIR_LEFT);
Entry::Occupied(OccupiedEntry { node: p, tree: self })
} else {
Entry::Vacant(VacantEntry {
node: null_mut(),
tree: self,
direction: DIR_LEFT,
key: First(),
})
}
}
#[inline]
pub fn last_entry<'a>(&'a mut self) -> Entry<'a, P, Tag, Last> {
if !self.root.is_null() {
let p = Self::bottom_child(unsafe { NonNull::new_unchecked(self.root) }, DIR_RIGHT);
Entry::Occupied(OccupiedEntry { node: p, tree: self })
} else {
Entry::Vacant(VacantEntry {
node: null_mut(),
tree: self,
direction: DIR_RIGHT,
key: Last(),
})
}
}
pub fn dump<F>(&self, print_cb: F)
where
F: Fn(&P::Target, usize),
{
let mut to_visit_stack: VecDeque<(*mut P::Target, usize)> = VecDeque::with_capacity(100);
if self.root.is_null() {
return;
}
to_visit_stack.push_front((self.root, 0));
while let Some((data, level)) = to_visit_stack.pop_front() {
unsafe {
let node = (*data).get_node();
let left = node.left();
if !left.is_null() {
to_visit_stack.push_back((left, level + 1));
}
let right = node.right();
if !right.is_null() {
to_visit_stack.push_back((right, level + 1));
}
print_cb(&*data, level);
}
}
}
#[inline]
pub fn validate(&self)
where
P::Target: Ord,
{
self.validate_with(P::Target::cmp)
}
fn validate_with<F>(&self, cmp_f: F)
where
F: Fn(&P::Target, &P::Target) -> Ordering,
{
use alloc::collections::BTreeMap;
let mut height_map = BTreeMap::<*mut P::Target, usize>::new();
let mut visited_stack: Vec<*mut P::Target> = Vec::with_capacity(100);
let mut to_visit_stack: Vec<*mut P::Target> = Vec::with_capacity(100);
let mut visit_count = 0;
if self.root.is_null() {
assert_eq!(self.count, 0);
return;
}
let mut push_stack =
|data: *mut P::Target,
_to_visit: &mut Vec<*mut P::Target>,
_visited: &mut Vec<*mut P::Target>,
_height_map: &mut BTreeMap<*mut P::Target, usize>| {
unsafe {
let node = (*data).get_node();
let left = node.left();
let mut has_child = false;
if !left.is_null() {
has_child = true;
assert!(
cmp_f(&*left, &*data) != Ordering::Greater,
"node {node:?} left not smaller"
);
assert_eq!(
(*left).get_node().get_parent(),
data,
"node {node:?} left parent not match"
);
_to_visit.push(left);
}
let right = node.right();
if !right.is_null() {
has_child = true;
assert!(
cmp_f(&*right, &*data) != Ordering::Less,
"node {node:?} right not larger"
);
assert_eq!(
(*right).get_node().get_parent(),
data,
"node {node:?} right parent not match"
);
_to_visit.push(right);
}
if !has_child {
_height_map.insert(data, 1);
assert_eq!(
node.balance, 0,
"leaf node {node:?} balance is not zero as leaf"
);
} else {
_visited.push(data);
}
}
visit_count += 1;
};
push_stack(self.root, &mut to_visit_stack, &mut visited_stack, &mut height_map);
while let Some(data) = to_visit_stack.pop() {
push_stack(data, &mut to_visit_stack, &mut visited_stack, &mut height_map);
}
while let Some(data) = visited_stack.pop() {
unsafe {
let node = (*data).get_node();
let left = node.left();
let mut balance: isize = 0;
let mut my_height = 0;
if !left.is_null() {
let left_height = *height_map.get(&left).unwrap();
balance -= left_height as isize;
my_height = left_height;
}
let right = node.right();
if !right.is_null() {
let right_height = *height_map.get(&right).unwrap();
balance += right_height as isize;
if my_height < right_height {
my_height = right_height;
}
}
height_map.insert(data, my_height + 1);
assert_eq!(node.balance, balance as i8, "non-leaf node {node:?} balance wrong");
}
}
assert_eq!(visit_count, self.count);
}
}
impl<P, Tag> Drop for AvlTree<P, Tag>
where
P: Pointer,
P::Target: AvlItem<Tag>,
{
fn drop(&mut self) {
let mut iter = AvlIntoIter::<P, Tag>::new(self.root, DIR_LEFT);
for _node in iter.by_ref() {}
core::mem::forget(iter);
}
}
impl<'a, P, Tag> core::iter::IntoIterator for &'a AvlTree<P, Tag>
where
P: Pointer,
P::Target: AvlItem<Tag>,
{
type Item = AvlNodeRef<'a, P>;
type IntoIter = AvlIter<'a, P, Tag>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl<P, Tag> core::iter::IntoIterator for AvlTree<P, Tag>
where
P: Pointer,
P::Target: AvlItem<Tag>,
{
type Item = P;
type IntoIter = AvlIntoIter<P, Tag>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
let node = self.root;
core::mem::forget(self);
AvlIntoIter::new(node, DIR_LEFT)
}
}
pub struct AvlNodeRef<'a, P: Pointer> {
node: NonNull<P::Target>,
_phan: PhantomData<&'a P>,
}
impl<'a, P: Pointer> fmt::Debug for AvlNodeRef<'a, P>
where
P::Target: fmt::Debug,
{
#[inline]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.as_ref().fmt(f)
}
}
impl<'a, P: Pointer> AsRef<P::Target> for AvlNodeRef<'a, P> {
#[inline(always)]
fn as_ref(&self) -> &P::Target {
unsafe { self.node.as_ref() }
}
}
impl<'a, P: Pointer> Deref for AvlNodeRef<'a, P> {
type Target = P::Target;
#[inline(always)]
fn deref(&self) -> &P::Target {
unsafe { self.node.as_ref() }
}
}
impl<'a, P: Pointer> AvlNodeRef<'a, P> {
#[inline]
fn new(p: *mut P::Target) -> Self {
Self { node: unsafe { NonNull::new_unchecked(p) }, _phan: Default::default() }
}
}
impl<'a, P: CloneablePointer> AvlNodeRef<'a, P> {
#[inline]
pub fn clone_ref(&self) -> P {
unsafe { CloneablePointer::from_raw_and_clone(self.node.as_ptr()) }
}
}