use std::cmp::Ordering;
pub(crate) const NIL: u32 = u32::MAX;
pub struct Treap<K, V> {
pub(crate) nodes: Vec<Node<K, V>>,
free_head: u32,
pub(crate) root: u32,
len: usize,
rng_state: u64,
}
pub(crate) struct Node<K, V> {
pub(crate) key: K,
pub(crate) value: V,
pub(crate) priority: u64,
pub(crate) left: u32,
pub(crate) right: u32,
}
impl<K: Ord, V> Treap<K, V> {
pub fn new(seed: u64) -> Self {
Self {
nodes: Vec::new(),
free_head: NIL,
root: NIL,
len: 0,
rng_state: seed | 1,
}
}
pub fn with_capacity(seed: u64, capacity: usize) -> Self {
Self {
nodes: Vec::with_capacity(capacity),
free_head: NIL,
root: NIL,
len: 0,
rng_state: seed | 1,
}
}
pub fn len(&self) -> usize {
self.len
}
pub fn is_empty(&self) -> bool {
self.len == 0
}
pub fn insert(&mut self, key: K, value: V) -> Option<V> {
let priority = self.next_priority();
let (new_root, replaced) = self.ins(self.root, key, value, priority);
self.root = new_root;
if replaced.is_none() {
self.len += 1;
}
replaced
}
pub fn get(&self, key: &K) -> Option<&V> {
let mut cur = self.root;
while cur != NIL {
let node = &self.nodes[cur as usize];
match key.cmp(&node.key) {
Ordering::Less => cur = node.left,
Ordering::Greater => cur = node.right,
Ordering::Equal => return Some(&node.value),
}
}
None
}
pub fn remove(&mut self, key: &K) -> Option<V> {
let (new_root, removed) = self.rem(self.root, key);
self.root = new_root;
if removed.is_some() {
self.len -= 1;
}
removed
}
pub fn collect_in_order(&self) -> Vec<(&K, &V)> {
let mut out = Vec::with_capacity(self.len);
self.in_order(self.root, &mut out);
out
}
fn next_priority(&mut self) -> u64 {
self.rng_state = self
.rng_state
.wrapping_mul(6364136223846793005)
.wrapping_add(1442695040888963407);
let mut z = self.rng_state;
z = (z ^ (z >> 30)).wrapping_mul(0xbf58476d1ce4e5b9);
z = (z ^ (z >> 27)).wrapping_mul(0x94d049bb133111eb);
z ^ (z >> 31)
}
fn alloc(&mut self, key: K, value: V, priority: u64) -> u32 {
if self.free_head != NIL {
let idx = self.free_head;
let slot = &mut self.nodes[idx as usize];
self.free_head = slot.left;
slot.key = key;
slot.value = value;
slot.priority = priority;
slot.left = NIL;
slot.right = NIL;
idx
} else {
let idx = self.nodes.len() as u32;
self.nodes.push(Node {
key,
value,
priority,
left: NIL,
right: NIL,
});
idx
}
}
fn free(&mut self, idx: u32) {
self.nodes[idx as usize].left = self.free_head;
self.free_head = idx;
}
fn ins(&mut self, root: u32, key: K, value: V, priority: u64) -> (u32, Option<V>) {
if root == NIL {
return (self.alloc(key, value, priority), None);
}
let cmp = key.cmp(&self.nodes[root as usize].key);
match cmp {
Ordering::Equal => {
let old = std::mem::replace(&mut self.nodes[root as usize].value, value);
(root, Some(old))
}
Ordering::Less => {
let left = self.nodes[root as usize].left;
let (new_left, replaced) = self.ins(left, key, value, priority);
self.nodes[root as usize].left = new_left;
let new_left_pri = self.nodes[new_left as usize].priority;
let root_pri = self.nodes[root as usize].priority;
let r = if new_left_pri > root_pri {
self.rotate_right(root)
} else {
root
};
(r, replaced)
}
Ordering::Greater => {
let right = self.nodes[root as usize].right;
let (new_right, replaced) = self.ins(right, key, value, priority);
self.nodes[root as usize].right = new_right;
let new_right_pri = self.nodes[new_right as usize].priority;
let root_pri = self.nodes[root as usize].priority;
let r = if new_right_pri > root_pri {
self.rotate_left(root)
} else {
root
};
(r, replaced)
}
}
}
fn rem(&mut self, root: u32, key: &K) -> (u32, Option<V>) {
if root == NIL {
return (NIL, None);
}
let cmp = key.cmp(&self.nodes[root as usize].key);
match cmp {
Ordering::Less => {
let left = self.nodes[root as usize].left;
let (new_left, removed) = self.rem(left, key);
self.nodes[root as usize].left = new_left;
(root, removed)
}
Ordering::Greater => {
let right = self.nodes[root as usize].right;
let (new_right, removed) = self.rem(right, key);
self.nodes[root as usize].right = new_right;
(root, removed)
}
Ordering::Equal => {
let left = self.nodes[root as usize].left;
let right = self.nodes[root as usize].right;
let value = unsafe {
std::ptr::read(&self.nodes[root as usize].value)
};
let merged = self.merge_subtrees(left, right);
self.free(root);
(merged, Some(value))
}
}
}
fn merge_subtrees(&mut self, left: u32, right: u32) -> u32 {
if left == NIL {
return right;
}
if right == NIL {
return left;
}
let l_pri = self.nodes[left as usize].priority;
let r_pri = self.nodes[right as usize].priority;
if l_pri > r_pri {
let l_right = self.nodes[left as usize].right;
let merged = self.merge_subtrees(l_right, right);
self.nodes[left as usize].right = merged;
left
} else {
let r_left = self.nodes[right as usize].left;
let merged = self.merge_subtrees(left, r_left);
self.nodes[right as usize].left = merged;
right
}
}
fn rotate_right(&mut self, idx: u32) -> u32 {
let left = self.nodes[idx as usize].left;
debug_assert!(left != NIL, "rotate_right requires left child");
let left_right = self.nodes[left as usize].right;
self.nodes[idx as usize].left = left_right;
self.nodes[left as usize].right = idx;
left
}
fn rotate_left(&mut self, idx: u32) -> u32 {
let right = self.nodes[idx as usize].right;
debug_assert!(right != NIL, "rotate_left requires right child");
let right_left = self.nodes[right as usize].left;
self.nodes[idx as usize].right = right_left;
self.nodes[right as usize].left = idx;
right
}
fn in_order<'a>(&'a self, idx: u32, out: &mut Vec<(&'a K, &'a V)>) {
if idx == NIL {
return;
}
let node = &self.nodes[idx as usize];
self.in_order(node.left, out);
out.push((&node.key, &node.value));
self.in_order(node.right, out);
}
}
#[cfg(feature = "harness")]
pub mod recipe;
#[cfg(any(
feature = "range-query",
feature = "persistent",
feature = "merge-split",
feature = "concurrent-reads",
))]
pub mod features;
#[cfg(feature = "concurrent-reads")]
pub use features::concurrent_reads::TreapSnapshot;
#[cfg(feature = "merge-split")]
pub use features::merge_split::SplittableTreap;
#[cfg(feature = "persistent")]
pub use features::persistent::PersistentTreap;
#[cfg(feature = "range-query")]
pub use features::range_query::{RangeBound, RangeIter};