use core::ptr;
pub struct Intrusive<T: HeapNode, Context: HeapContext<T>> {
pub root: *mut T,
pub context: Context,
}
pub trait HeapContext<T> {
unsafe fn less(&self, a: *mut T, b: *mut T) -> bool;
}
pub trait HeapNode: Sized {
fn heap(&mut self) -> &mut IntrusiveField<Self>;
}
impl<T: HeapNode, Context: HeapContext<T>> Default for Intrusive<T, Context>
where
Context: Default,
{
fn default() -> Self {
Self {
root: ptr::null_mut(),
context: Context::default(),
}
}
}
impl<T: HeapNode, Context: HeapContext<T>> Intrusive<T, Context> {
pub unsafe fn insert(&mut self, v: *mut T) {
self.root = if !self.root.is_null() {
let root = self.root;
self.meld(v, root)
} else {
v
};
}
pub fn peek(&self) -> *mut T {
self.root
}
pub unsafe fn count(&self) -> usize {
Self::count_internal(self.root)
}
unsafe fn count_internal(node: *mut T) -> usize {
if node.is_null() {
return 0;
}
let current = node;
let mut result: usize = 1;
result += Self::count_internal((*current).heap().child);
result += Self::count_internal((*current).heap().next);
result
}
pub unsafe fn find_max(&self) -> *mut T {
if self.root.is_null() {
return ptr::null_mut();
}
let root = self.root;
Self::find_max_internal(&self.context, root, root)
}
unsafe fn find_max_internal(ctx: &Context, node: *mut T, current_max: *mut T) -> *mut T {
let mut max_so_far = current_max;
if ctx.less(max_so_far, node) {
max_so_far = node;
}
let child = (*node).heap().child;
if !child.is_null() {
max_so_far = Self::find_max_internal(ctx, child, max_so_far);
}
let next_sibling = (*node).heap().next;
if !next_sibling.is_null() {
max_so_far = Self::find_max_internal(ctx, next_sibling, max_so_far);
}
max_so_far
}
pub unsafe fn delete_min(&mut self) -> *mut T {
if self.root.is_null() {
return ptr::null_mut();
}
let root = self.root;
let child = (*root).heap().child;
self.root = if !child.is_null() {
self.combine_siblings(child)
} else {
ptr::null_mut()
};
*(*root).heap() = IntrusiveField::default();
root
}
pub unsafe fn remove(&mut self, v: *mut T) {
let prev = (*v).heap().prev;
if prev.is_null() {
debug_assert!(self.root == v);
let _ = self.delete_min();
return;
}
let v_next = (*v).heap().next;
if !v_next.is_null() {
(*v_next).heap().prev = prev;
}
if (*prev).heap().child == v {
(*prev).heap().child = v_next;
} else {
(*prev).heap().next = v_next;
}
(*v).heap().prev = ptr::null_mut();
(*v).heap().next = ptr::null_mut();
let child = (*v).heap().child;
if child.is_null() {
return;
}
(*v).heap().child = ptr::null_mut();
let x = self.combine_siblings(child);
self.root = self.meld(x, self.root);
}
unsafe fn meld(&mut self, a: *mut T, b: *mut T) -> *mut T {
debug_assert!((*a).heap().next.is_null());
if self.context.less(a, b) {
(*b).heap().prev = a;
let b_next = (*b).heap().next;
if !b_next.is_null() {
(*a).heap().next = b_next;
(*b_next).heap().prev = a;
(*b).heap().next = ptr::null_mut();
}
let a_child = (*a).heap().child;
if !a_child.is_null() {
(*b).heap().next = a_child;
(*a_child).heap().prev = b;
}
(*a).heap().child = b;
return a;
}
(*b).heap().prev = (*a).heap().prev;
(*a).heap().prev = b;
let b_child = (*b).heap().child;
if !b_child.is_null() {
(*a).heap().next = b_child;
(*b_child).heap().prev = a;
}
(*b).heap().child = a;
b
}
unsafe fn combine_siblings(&mut self, left: *mut T) -> *mut T {
(*left).heap().prev = ptr::null_mut();
let mut root: *mut T = 'root: {
let mut a: *mut T = left;
loop {
let mut b = (*a).heap().next;
if b.is_null() {
break 'root a;
}
(*a).heap().next = ptr::null_mut();
b = self.meld(a, b);
let next_a = (*b).heap().next;
if next_a.is_null() {
break 'root b;
}
a = next_a;
}
};
loop {
let b = (*root).heap().prev;
if b.is_null() {
return root;
}
(*b).heap().next = ptr::null_mut();
root = self.meld(b, root);
}
}
}
pub struct IntrusiveField<T> {
pub child: *mut T,
pub prev: *mut T,
pub next: *mut T,
}
impl<T> Default for IntrusiveField<T> {
fn default() -> Self {
Self {
child: ptr::null_mut(),
prev: ptr::null_mut(),
next: ptr::null_mut(),
}
}
}