See: http://aosabook.org/en/posa/parsing-xml-at-the-speed-of-ligh...
Iteration on array is faster (cache locality) than DL list traversal. And there are issues when you traverse tree while changing it.
In any case I've found that storing child nodes as m_children collection is more convenient in many cases. At least in Sciter (https://sciter.com).
struct node {
weak_ref<element> m_parent;
uint m_node_index;
}
struct element : node {
vector<ref<node>> m_children; // strict ownership, sic!
}I haven't looked at the code but that's my first impression given the nomenclature.
You may have children accounted as DL list and so each Node should have m_next / m_previous node references. + Parent node to have m_first_child reference (if list is circular). + m_parent (Node) reference.
So you need 4 pointers per each non-terminal node. Or 3 pointers for terminals.
Otherwise (vector of children):
You need only m_parent (Node) reference in terminals. And in container nodes additional vector<NodePtr> m_children; to store child references.
You want sibling nodes otherwise you will have to traverse back to the root node sometimes to find a sibling.
You do need parent, check this: https://developer.mozilla.org/en-US/docs/Web/API/Node/parent...
> You want sibling nodes otherwise you will have to traverse back to the root node sometimes to find a sibling.
The only need for this is in Node.nextSibling implementation: https://developer.mozilla.org/en-US/docs/Web/API/Node/nextSi...
Where vector<>::find is pretty sufficient.
But in reality (at least in my Sciter) node stores its index in parent's m_children so it is O(1) operation.
m_children + m_parent are enough for tree representation.