A clean, Pythonic implementation of an immutable treap (tree + heap) data structure that provides O(log n) expected operations with a natural Python API.
A treap is a randomized binary search tree that maintains both:
- Binary search tree property: Keys are ordered (left subtree < node < right subtree)
 - Heap property: Each node has a random priority, with parent priority ≥ child priority
 
The combination of these properties ensures O(log n) expected time complexity for basic operations while maintaining simplicity of implementation.
This implementation is immutable - all operations return new treap instances rather than modifying existing ones, making it thread-safe and suitable for functional programming paradigms.
- Pythonic API: Dict-like access with 
[],in,len(), iteration - Any Comparable Keys: Works with integers, strings, tuples, or any comparable type
 - Set Operations: Union (
|), intersection (&), difference (-) - Order Statistics: 
select(k)for k-th smallest,rank(key)for position - Range Queries: Efficient queries over key ranges
 - Immutability: All operations return new instances
 - Memory Efficient: Uses 
__slots__and generators - Thread-Safe: Safe for concurrent reads due to immutability
 
# Clone the repository
git clone <repository-url>
cd <repository-directory>
# Install dependencies
make installThe package provides a Pythonic API that works with any comparable type:
from treap import Treap, treap
# Create a new treap
t = Treap()
# Add items
t = t.set("apple", 1)
t = t.set("banana", 2)
t = t.set("cherry", 3)
# Get items (dict-like access)
print(t["apple"])  # 1
print(t.get("date", 0))  # 0 (default)
# Check membership
if "banana" in t:
    print("Found banana!")
# Delete items
t = t.delete("apple")
# Get min/max
print(t.min_key())  # "banana"
print(t.max_key())  # "cherry"# From dict
t = Treap.from_dict({"x": 10, "y": 20, "z": 30})
# From pairs
t = Treap.from_pairs([(1, "one"), (2, "two"), (3, "three")])
# Convenience function
t = treap((1, "a"), (2, "b"), (3, "c"))
t = treap(x=10, y=20, z=30)t1 = treap((1, "a"), (2, "b"), (3, "c"))
t2 = treap((2, "B"), (3, "C"), (4, "D"))
# Union with | operator
t_union = t1 | t2
# Intersection with & operator
t_intersect = t1 & t2
# Difference with - operator
t_diff = t1 - t2t = treap((3, "three"), (1, "one"), (4, "four"), (2, "two"))
# Iterate keys in sorted order
for key in t:
    print(key)  # 1, 2, 3, 4
# Get all keys/values/items
keys = list(t.keys())     # [1, 2, 3, 4]
values = list(t.values())  # ["one", "two", "three", "four"]
items = list(t.items())    # [(1, "one"), (2, "two"), ...]t = Treap()
for i in range(10):
    t = t.set(i, str(i))
# Get items in range [3, 6]
for key, value in t.range(3, 6):
    print(f"{key}: {value}")
# Exclusive range [3, 6)
for key, value in t.range(3, 6, inclusive=False):
    print(f"{key}: {value}")# Get k-th smallest item (0-indexed)
item = t.select(5)  # 6th smallest item
# Get rank of key (number of items less than it)
rank = t.rank(7)  # Number of items < 7Run the test suite:
make test| Operation | Time Complexity | Notes | 
|---|---|---|
set, delete, get | 
O(log n) expected | Randomized structure | 
len() | 
O(1) | Cached at node level | 
min_key, max_key | 
O(log n) | Tree traversal | 
select(k), rank(key) | 
O(log n) | Uses size caching | 
range(start, end) | 
O(k + log n) | k = items in range | 
| Union, Intersection | O(m log(n/m + 1)) | m ≤ n | 
| Iteration | O(n) | In-order traversal | 
- Node overhead: ~40% less than dict due to 
__slots__ - Immutability cost: O(log n) new nodes per modification
 - Total structure: O(n) nodes
 
- Thread Safety: Multiple threads can read the same treap safely
 - Persistence: Previous versions remain accessible
 - Undo/Redo: Easy to implement by keeping references
 - Debugging: State changes are explicit and traceable
 
Compare treap performance against Python's dict:
make benchmark        # Standard benchmark (1K, 10K, 100K items)
make benchmark-small  # Quick benchmark (100, 500, 1K items)
make benchmark-large  # Large benchmark (10K, 50K, 100K items)Use Treap when you need:
- Sorted iteration over keys
 - Range queries
 - Immutability/persistence
 - Set operations on large datasets
 - Order statistics (select k-th, rank)
 
Use Dict when you need:
- Fastest possible O(1) lookups
 - Frequent modifications
 - No ordering requirements
 
The implementation is based on the paper: "Fast Set Operations Using Treaps" by Guy E. Blelloch and Margaret Reid-Miller
See LICENSE
Contributions are welcome! Please ensure:
- All tests pass (
make test) - New features include tests
 - Code follows existing style conventions