Persistent structural sharing tree for Calcit Runtime
a variant of 2-3 tree, with enhancements on ternary branching, optimized with tricks like finger-tree.
t.pop_left() and t.push_right(..) is optimized to be amortized O(1) at best cases and O(log n) when restructuring involed.
Tree layout from 0 to 159 watch video or try live demo.

Usage
Docs https://docs.rs/im_ternary_tree/ .
use TernaryTreeList;
println!;
// assoc
let origin5 = ;
let data5 = from;
let updated = data5.assoc;
println!;
println!;
assert_eq!;
Optimizations
方案设计的中文介绍 https://www.bilibili.com/video/BV1z44y1a7a6/
This library has special optimizations on push_right and pop_left with tricks from finger-tree.
And as its size grows, it always operates on a shallow branch at right end, wasting fewer nodes for indexing new elements, a random demo looks like:

Also the left branches are kept shallow on purpose so it can be cheaper in pop_left. This trick is inspired by finger-tree.
Performance
Benchmarks comparing TernaryTreeList with std::vec::Vec and std::collections::VecDeque show a clear performance profile. As an immutable data structure, TernaryTreeList has some overhead compared to its mutable counterparts, but offers significant advantages in specific scenarios.
-
push_right/drop_right(Appending/Popping from the tail):VecandVecDequeare significantly faster, as they are mutable and optimized for O(1) amortized operations at the tail.TernaryTreeListis slower due to the nature of immutable structures, which require creating new tree nodes.
-
push_left/drop_left(Prepending/Popping from the head):TernaryTreeListis dramatically faster thanVec.Vec::insert(0, ...)is an O(n) operation, whileTernaryTreeList's finger-tree-inspired optimizations make head operations much more efficient.VecDequeis still the fastest, as it is a mutable data structure specifically designed for O(1) head and tail operations.
Conclusion:
- Use
TernaryTreeListwhen:- You need an immutable (persistent) list.
- You require efficient push and pop operations on both ends of the list.
- Use
VecorVecDequewhen:- Mutability is acceptable.
- You need the absolute best performance for purely mutable operations.
Known Issues
- lack of optimizations on
pop_right. - elements in the middle may be deeply nested, resulting in slow performance.
License
MIT