VebTree - Van Emde Boas Tree
A high-performance Van Emde Boas (vEB) tree implementation for Ruby with a C++17 core.
Provides O(log log U) time complexity for integer set operations, making it exponentially faster than balanced BSTs for many workloads.
โจ Features
- โก Blazing Fast โ
O(log log U)operations for insert, delete, search, successor, and predecessor - ๐ฅ Native Performance โ core implemented in C++17
- ๐งโ๐ป Simple API โ clean, idiomatic Ruby interface
- ๐งฉ Memory Efficient โ lazy cluster allocation to minimize space usage
- โ Battle Tested โ comprehensive test suite included
๐ฆ Installation
Requirements
- Ruby: 2.7 or higher
-
C++17 compatible compiler:
- Linux: GCC 7+ or Clang 5+
- macOS: Xcode Command Line Tools
- Windows: MinGW-w64 or MSVC 2017+
Install via RubyGems
gem install veb_treeInstall from Source
git clone https://github.com/yourusername/veb_tree.git
cd veb_tree
bundle install
rake compile
rake test
gem build veb_tree.gemspec
gem install veb_tree-*.gem๐ Quick Start
require 'veb_tree'
# Create a tree with universe size (rounded to next power of 2)
tree = VebTree::Tree.new(1000) # Actual size: 1024
# Insert elements
tree.insert(42)
tree.insert(100)
tree.insert(7)
tree.insert(500)
# Membership check
tree.include?(42) # => true
tree.include?(99) # => false
# Min/Max
tree.min # => 7
tree.max # => 500
# Successor / Predecessor
tree.successor(42) # => 100
tree.predecessor(100) # => 42
# Size & emptiness
tree.size # => 4
tree.empty? # => false
# Iterate in sorted order
tree.each { |key| puts key }
# Output: 7, 42, 100, 500
# Convert to array
tree.to_a # => [7, 42, 100, 500]
# Delete elements
tree.delete(42) # => true
tree.delete(42) # => false (already removed)
# Clear all elements
tree.clear๐ API Reference
Constructor
VebTree::Tree.new(universe_size)-
universe_size (Integer) โ maximum value that can be stored (exclusive).
Automatically rounded up to the next power of 2. -
Returns:
VebTree::Treeinstance -
Raises:
ArgumentErrorif universe_size โค 0
Example:
tree = VebTree::Tree.new(100)
tree.universe_size # => 128Core Operations
Insert
tree.insert(key) โ Boolean- Inserts a key.
- Time: O(log log U)
- Returns
trueif inserted,falseif already present.
Delete
tree.delete(key) โ Boolean- Removes a key.
- Time: O(log log U)
- Returns
trueif deleted,falseif not found.
Membership
tree.include?(key) โ Boolean
tree.member?(key) # alias- Checks if key exists.
- Time: O(log log U)
Min / Max
tree.min โ Integer or nil
tree.max โ Integer or nil- Returns smallest or largest key.
- Time: O(1)
Successor / Predecessor
tree.successor(key) โ Integer or nil
tree.predecessor(key) โ Integer or nil- Finds next higher or next lower key.
- Time: O(log log U)
Utility Methods
-
tree.sizeโ number of elements (O(1)) -
tree.empty?โ true/false (O(1)) -
tree.universe_sizeโ current universe size -
tree.clearโ removes all elements
Enumeration
The tree includes Enumerable, so all Ruby iteration helpers work:
tree.each { |key| puts key }
tree.to_a # => [7, 42, 100, 500]
tree.map { |x| x * 2 } # => [14, 84, 200, 1000]
tree.select { |x| x > 50 } # => [100, 500]
tree.count # => 4๐ Performance
| Operation | vEB Tree | Balanced BST |
|---|---|---|
| Insert | O(log log U) | O(log n) |
| Delete | O(log log U) | O(log n) |
| Search | O(log log U) | O(log n) |
| Successor | O(log log U) | O(log n) |
| Predecessor | O(log log U) | O(log n) |
| Min/Max | O(1) | O(log n) |
- U = universe size (max key)
- n = number of stored elements
vEB trees are best for bounded integer sets with frequent successor/predecessor/min/max queries.
โ ๏ธ Avoid when:
- Universe size is huge (> 2^24)
- Need arbitrary objects (only integers supported)
- Extremely memory constrained
๐พ Space Complexity
- Theoretical: O(U)
- Optimized with lazy allocation: only used clusters consume memory
Practical Usage:
- Universe
2^16(65K): ~hundreds of KB - Universe
2^20(1M): ~few MB - Universe
2^24(16M): ~tens of MB
โ ๏ธ Thread Safety
This implementation is NOT thread-safe.
For concurrency, wrap operations with a Mutex:
require 'thread'
tree = VebTree::Tree.new(1000)
mutex = Mutex.new
mutex.synchronize do
tree.insert(42)
end๐ Error Handling
tree = VebTree::Tree.new(0) # ArgumentError: Universe size must be > 0
tree.insert(-1) # ArgumentError: Key must be non-negative
tree.insert(200) # ArgumentError: Key exceeds universe size
tree.include?(999) # => false
tree.successor(999) # => nil๐งช Examples
Range Query Simulation
tree = VebTree::Tree.new(10000)
100.times { tree.insert(rand(10000)) }
current = tree.successor(999) # first โฅ 1000
result = []
while current && current <= 2000
result << current
current = tree.successor(current)
endK-th Smallest Element
def kth_smallest(tree, k)
current = tree.min
(k - 1).times do
return nil unless current
current = tree.successor(current)
end
current
end
tree = VebTree::Tree.new(1000)
[5, 10, 3, 50].each { |x| tree.insert(x) }
kth_smallest(tree, 2) # => 5๐ง Development
# Clone repo
git clone https://github.com/yourusername/veb_tree.git
cd veb_tree
# Install dependencies
bundle install
# Compile extension
rake compile
# Run tests
rake test
# Clean build
rake clean๐ค Contributing
Bug reports and pull requests are welcome at:
๐ https://github.com/abhinvv1/Van-Emde-Boas-tree
๐ License
This gem is available as open source under the MIT License.
๐ References & Credits
- Based on the Van Emde Boas tree described by Peter van Emde Boas (1975)
- Cormen, T. H., et al. (2009). Introduction to Algorithms (3rd ed.), Chapter 20
๐๏ธ Changelog
See CHANGELOG.md for version history.