d-ary Heap Priority Queue (Rust) v2.5.0
Wikipedia-standard d-ary heap implementation with O(1) item lookup and configurable arity.
Key Features
- d-ary heap (not binary): Configurable arity
d(number of children per node) - Min/Max flexibility: Supports both min-heap and max-heap behavior via comparators
- O(1) item lookup: Internal hash map enables efficient priority updates
- Efficient operations:
- O(1):
front(),peek(),len(),is_empty(),contains(),get_position() - O(log_d n):
insert(),increase_priority() - O(d × log_d n):
pop(),decrease_priority() - O(n):
insert_many()(Floyd's heapify),to_array()
- O(1):
- Cross-language API: Unified methods matching C++, Go, Zig, and TypeScript implementations
- Rust-idiomatic: Uses
Result<T, Error>andOption<T>return types
Installation
Add to your Cargo.toml:
[]
= "2.5.0"
Quick Start
use ;
Usage Examples
Basic Operations
use ;
let mut heap = new.unwrap;
// Insert items
heap.insert;
heap.insert;
heap.insert;
// Check properties
assert_eq!;
assert!;
assert_eq!;
// Access highest priority (front panics if empty, peek returns Option)
assert_eq!;
assert_eq!;
// Remove items
assert_eq!;
assert_eq!;
assert_eq!;
assert_eq!;
Max-Heap Example
use ;
let mut heap = new.unwrap;
heap.insert;
heap.insert;
heap.insert;
// Max-heap: highest value has highest priority
assert_eq!;
Bulk Operations
use ;
let mut heap = new.unwrap;
// Insert many items at once (O(n) via Floyd's heapify)
heap.insert_many;
assert_eq!;
// Pop multiple items at once
let items = heap.pop_many;
assert_eq!;
// Get heap contents as array
let remaining = heap.to_array;
assert_eq!;
Priority Updates
use ;
use ;
// Important: Hash/Eq must be based on identity (id), not priority (cost)
let mut heap = new.unwrap;
heap.insert;
heap.insert;
// Increase priority (for min-heap: lower cost = higher priority)
heap.increase_priority.unwrap;
assert_eq!;
// Decrease priority (for min-heap: higher cost = lower priority)
heap.decrease_priority.unwrap;
assert_eq!;
// Update priority when direction is unknown
heap.update_priority.unwrap;
// Check item position (O(1) lookup)
assert!;
Error Handling
use ;
// Invalid arity returns error
let result = new;
assert_eq!;
let mut heap = new.unwrap;
heap.insert;
// Item not found error
assert_eq!;
// Index out of bounds error
assert_eq!;
// Clear with invalid arity
assert_eq!;
API Reference
Core Types
| Type | Description |
|---|---|
PriorityQueue<T, C> |
The main heap type |
MinBy<F> |
Comparator wrapper for min-heap behavior |
MaxBy<F> |
Comparator wrapper for max-heap behavior |
Position |
Type alias for position indices (usize) |
Error |
Error enum for fallible operations |
Error Variants
| Variant | Description |
|---|---|
Error::InvalidArity |
Arity (d) must be >= 1 |
Error::ItemNotFound |
Item not found in the priority queue |
Error::IndexOutOfBounds |
Index is out of bounds |
Error::EmptyQueue |
Operation requires a non-empty queue |
Methods
| Method | Return | Complexity | Description |
|---|---|---|---|
new(d, comparator) |
Result<Self, Error> |
O(1) | Create new heap with arity d |
with_first(d, comparator, item) |
Result<Self, Error> |
O(1) | Create heap with initial item |
len() |
usize |
O(1) | Number of items |
is_empty() |
bool |
O(1) | Check if empty |
d() |
usize |
O(1) | Get arity |
contains(item) |
bool |
O(1) | Check membership |
get_position(item) |
Option<Position> |
O(1) | Get item's position index |
front() |
&T |
O(1) | Highest priority item (panics if empty) |
peek() |
Option<&T> |
O(1) | Highest priority item (safe) |
insert(item) |
() |
O(log_d n) | Add new item |
insert_many(items) |
() |
O(n) | Bulk insert via Floyd's heapify |
increase_priority(item) |
Result<(), Error> |
O(log_d n) | Update to higher priority |
decrease_priority(item) |
Result<(), Error> |
O(d·log_d n) | Update to lower priority |
update_priority(item) |
Result<(), Error> |
O((d+1)·log_d n) | Update priority (any direction) |
increase_priority_by_index(i) |
Result<(), Error> |
O(log_d n) | Increase priority at index |
decrease_priority_by_index(i) |
Result<(), Error> |
O(d·log_d n) | Decrease priority at index |
update_priority_by_index(i) |
Result<(), Error> |
O((d+1)·log_d n) | Update at index (any direction) |
pop() |
Option<T> |
O(d·log_d n) | Remove highest priority item |
pop_many(count) |
Vec<T> |
O(count·d·log_d n) | Remove multiple items |
to_array() |
Vec<T> |
O(n) | Copy heap contents |
clear(new_d?) |
Result<(), Error> |
O(1) | Remove all items |
to_string() |
String |
O(n) | String representation |
Traits
| Trait | Description |
|---|---|
PriorityCompare<T> |
Define custom priority ordering |
Display |
String representation ({item1, item2, ...}) |
Performance Considerations
Choosing Optimal Arity (d)
| Arity | Use Case | Insert | Pop |
|---|---|---|---|
| d=2 | Mixed workloads | O(log n) | O(log n) |
| d=3-4 | Insert-heavy | O(log₃ n) | O(3·log₃ n) |
| d=8+ | Very insert-heavy | O(log₈ n) | O(8·log₈ n) |
Recommendation: Start with d=4 for most workloads.
Optimization Tips
- Use bulk insert:
insert_many()is O(n) vs O(n log n) for individual inserts - Choose d wisely: Benchmark with your workload (d=4 often optimal)
- Use simple comparators: Inline closures are faster than complex functions
- Stable identity: Ensure Hash/Eq are based on stable identity, not priority
Cross-Language Compatibility
This implementation provides API parity with:
- C++:
PriorityQueue<T>inCpp/PriorityQueue.h - Go:
PriorityQueue[T]inGo/src/dheap.go - Zig:
DHeap(T)inzig/src/d_heap.zig - TypeScript:
PriorityQueue<T>inTypeScript/src/PriorityQueue.ts
All implementations share:
- Identical time complexities
- Unified method names (with language-appropriate casing)
- Cross-language API consistency
What is a d-ary Heap?
A d-ary heap is a tree structure where:
- Each node has up to d children (configurable arity)
- The root contains the highest-priority item
- Children are unordered (unlike binary heaps)
- Heap property: Each parent has higher priority than all children
- Complete tree: Filled left-to-right, level by level
Advantages over Binary Heaps (d=2)
- Shallower tree: Height is log_d(n) instead of log₂(n)
- Faster inserts: O(log_d n) vs O(log₂ n)
- Configurable: Optimize for your specific workload
Trade-offs
- Slower pops: O(d·log_d n) vs O(log₂ n)
- More comparisons: Each pop examines up to d children
- Memory: Slightly higher overhead for position tracking
Reference Implementation
This implementation follows the d-ary heap specification from:
- Wikipedia: D-ary heap
- Network Flows textbook: Section A.3, pp. 773–778
- Ravindra Ahuja, Thomas Magnanti & James Orlin
- Prentice Hall (1993)
- Book information
Testing
# Run all tests
# Run specific test
# Run demo
License
Apache License 2.0 - See LICENSE for details.