Skip to main content

oxihuman_core/
treap_map.rs

1// Copyright (C) 2026 COOLJAPAN OU (Team KitaSan)
2// SPDX-License-Identifier: Apache-2.0
3#![allow(dead_code)]
4
5//! Treap map stub — randomized BST (BST + heap on random priorities).
6
7/// A node in the treap.
8#[derive(Debug)]
9struct TreapNode<K, V> {
10    key: K,
11    val: V,
12    priority: u64,
13    left: Option<Box<TreapNode<K, V>>>,
14    right: Option<Box<TreapNode<K, V>>>,
15}
16
17impl<K: Ord, V> TreapNode<K, V> {
18    fn new(key: K, val: V, priority: u64) -> Box<Self> {
19        Box::new(TreapNode {
20            key,
21            val,
22            priority,
23            left: None,
24            right: None,
25        })
26    }
27
28    fn rotate_right(mut y: Box<TreapNode<K, V>>) -> Box<TreapNode<K, V>> {
29        let Some(mut x) = y.left.take() else { return y };
30        y.left = x.right.take();
31        x.right = Some(y);
32        x
33    }
34
35    fn rotate_left(mut x: Box<TreapNode<K, V>>) -> Box<TreapNode<K, V>> {
36        let Some(mut y) = x.right.take() else {
37            return x;
38        };
39        x.right = y.left.take();
40        y.left = Some(x);
41        y
42    }
43
44    fn insert(
45        node: Option<Box<TreapNode<K, V>>>,
46        key: K,
47        val: V,
48        prio: u64,
49    ) -> (Box<TreapNode<K, V>>, bool) {
50        let Some(mut n) = node else {
51            return (Self::new(key, val, prio), true);
52        };
53        let added;
54        match key.cmp(&n.key) {
55            std::cmp::Ordering::Equal => {
56                n.val = val;
57                return (n, false);
58            }
59            std::cmp::Ordering::Less => {
60                let (l, a) = Self::insert(n.left.take(), key, val, prio);
61                n.left = Some(l);
62                added = a;
63                if n.left.as_ref().is_some_and(|l| l.priority > n.priority) {
64                    n = Self::rotate_right(n);
65                }
66            }
67            std::cmp::Ordering::Greater => {
68                let (r, a) = Self::insert(n.right.take(), key, val, prio);
69                n.right = Some(r);
70                added = a;
71                if n.right.as_ref().is_some_and(|r| r.priority > n.priority) {
72                    n = Self::rotate_left(n);
73                }
74            }
75        }
76        (n, added)
77    }
78
79    fn get(&self, key: &K) -> Option<&V> {
80        match key.cmp(&self.key) {
81            std::cmp::Ordering::Equal => Some(&self.val),
82            std::cmp::Ordering::Less => self.left.as_ref()?.get(key),
83            std::cmp::Ordering::Greater => self.right.as_ref()?.get(key),
84        }
85    }
86}
87
88/// Ordered map backed by a treap.
89pub struct TreapMap<K: Ord, V> {
90    root: Option<Box<TreapNode<K, V>>>,
91    count: usize,
92    rng: u64,
93}
94
95impl<K: Ord, V> TreapMap<K, V> {
96    /// Create a new empty treap map.
97    pub fn new() -> Self {
98        TreapMap {
99            root: None,
100            count: 0,
101            rng: 0x853c_49e6_748f_ea9b,
102        }
103    }
104
105    fn next_prio(&mut self) -> u64 {
106        self.rng ^= self.rng << 13;
107        self.rng ^= self.rng >> 7;
108        self.rng ^= self.rng << 17;
109        self.rng
110    }
111
112    /// Insert or update a key-value pair.
113    pub fn insert(&mut self, key: K, val: V) {
114        let prio = self.next_prio();
115        let (node, added) = TreapNode::insert(self.root.take(), key, val, prio);
116        self.root = Some(node);
117        if added {
118            self.count += 1;
119        }
120    }
121
122    /// Look up a key.
123    pub fn get(&self, key: &K) -> Option<&V> {
124        self.root.as_ref()?.get(key)
125    }
126
127    /// Number of entries.
128    pub fn len(&self) -> usize {
129        self.count
130    }
131
132    /// True if the map is empty.
133    pub fn is_empty(&self) -> bool {
134        self.count == 0
135    }
136
137    /// Check if a key is present.
138    pub fn contains_key(&self, key: &K) -> bool {
139        self.get(key).is_some()
140    }
141}
142
143impl<K: Ord, V> Default for TreapMap<K, V> {
144    fn default() -> Self {
145        Self::new()
146    }
147}
148
149#[cfg(test)]
150mod tests {
151    use super::*;
152
153    #[test]
154    fn test_insert_and_get() {
155        let mut t: TreapMap<u32, u32> = TreapMap::new();
156        t.insert(5, 50);
157        assert_eq!(t.get(&5), Some(&50) /* basic get */);
158    }
159
160    #[test]
161    fn test_missing_key() {
162        let t: TreapMap<u32, u32> = TreapMap::new();
163        assert_eq!(t.get(&1), None /* key absent */);
164    }
165
166    #[test]
167    fn test_update() {
168        let mut t: TreapMap<u32, u32> = TreapMap::new();
169        t.insert(2, 20);
170        t.insert(2, 99);
171        assert_eq!(t.get(&2), Some(&99) /* updated value */);
172    }
173
174    #[test]
175    fn test_len() {
176        let mut t: TreapMap<u32, u32> = TreapMap::new();
177        t.insert(1, 1);
178        t.insert(2, 2);
179        assert_eq!(t.len(), 2);
180    }
181
182    #[test]
183    fn test_is_empty() {
184        let t: TreapMap<u32, u32> = TreapMap::new();
185        assert!(t.is_empty());
186    }
187
188    #[test]
189    fn test_many_inserts() {
190        let mut t: TreapMap<u32, u32> = TreapMap::new();
191        for i in 0u32..50 {
192            t.insert(i, i * 3);
193        }
194        for i in 0u32..50 {
195            assert_eq!(t.get(&i), Some(&(i * 3)));
196        }
197    }
198
199    #[test]
200    fn test_contains_key() {
201        let mut t: TreapMap<u32, u32> = TreapMap::new();
202        t.insert(9, 90);
203        assert!(t.contains_key(&9));
204        assert!(!t.contains_key(&10));
205    }
206
207    #[test]
208    fn test_reverse_inserts() {
209        let mut t: TreapMap<u32, u32> = TreapMap::new();
210        for i in (0u32..30).rev() {
211            t.insert(i, i);
212        }
213        assert_eq!(t.len(), 30);
214    }
215
216    #[test]
217    fn test_default() {
218        let t: TreapMap<u32, u32> = TreapMap::default();
219        assert!(t.is_empty());
220    }
221}