4 ms·
> The solution is surprisingly simple: we can store every node in a dynamic array, (a Vec in Rust) and use indices into this vector to refer to other nodes. Thi
by orlp 3y ago
> The solution is surprisingly simple: we can store every node in a dynamic array, (a Vec in Rust) and use indices into this vector to refer to other nodes. This solves the ownership problem because the vector now owns all the nodes. And by simply storing the index of the parent in every node we can navigate the tree in both directions without having to use any unsafe code.
> This all hinges on the assumption that once we’ve inserted a node into the vector its index never changes. Inserting new nodes doesn’t cause any issues: we just append them to the end. Removing a node however would be doubly bad: not only is it a linear operation (because we’re now using a vector instead of a tree), but it would also invalidate all the indices of the nodes that come after it.
If you use my crate slotmap (https://docs.rs/slotmap/latest/slotmap/ https://docs.rs/slotmap/latest/slotmap/) you can support deletions without worrying about indices shifting or 'indices' (slotmap calls them keys) ever pointing at different values, as the keys in slotmap also come with a version number.
- deleted 3y ago[deleted]
- Kinrany 3y agoWould it work in a CRDT context, where ordering is hard and so versions could only be local?
- orlp 3y agoThere are two kinds of versions here. The CRDT version and Slotmap's internal version. I am not proposing you merge the two concepts, rather that instead of a Vec and simple indexes you use a Slotmap and keys, which then does allow deletion at the data structure level (figuring out the deletion in a CRDT fashion is something else). The rest of the design would stay the same. I'm not even saying that it's a particularly good fit here, especially if you wish to support undos. It's more of a future tip for when you want to use a similar pattern in a context where you really do want deletions.