1

I have implemented a simple binary tree class in C++. have using smart pointers objects to hold the pointers to each node (shared for children and weak for parent).

I was trying to implement a nested class for custom iterator (in-order, pre-order and post-order), but I couldn't figure out how to implement efficiently the .next() method. how can I get current position in traversal without holding the entire tree in a priority queue.

the tree nodes are a struct -

struct node : std::enable_shared_from_this
{
    T _val;
    std::weak_ptr<node> _parent;
    std::shared_ptr<node> _leftChild;
    std::shared_ptr<node> _rightChild;

    // CONSTRUCTORS
    node(T val): _val(val){}
    node(T val, weak_ptr<node> parent): _val(val), _parent(parent){}
};
Kfir Ettinger
  • 584
  • 4
  • 13
  • what is .next()? why not implement in-order, pre-order and post-order recursively? – EyaS Jun 07 '21 at 08:38
  • Do you really need iterator? how about a (template) function member`in_order_traversal(std::function)`? – Jarod42 Jun 07 '21 at 08:39
  • So what you are asking is how to determine the next node according to one of the orders. What is the problem? Looking at a node in a tree, which you just have traversed already, what keeps you from identifying the next one? Where does a queue get into the game? Please explain your reasoning. Consider using an ascii-art tree diagram to visualise your question and the specific problem you encounter. I ask because I have the impression that the existence of the parent pointer (i.e. the difference to a standard binary tree) makes things quite easy. – Yunnosch Jun 07 '21 at 08:54
  • There is a difference between doing a (in-order) traversal, and providing **iterator** for that traversal. (the former is trivial thanks to recursion, the latter is more complicated). – Jarod42 Jun 07 '21 at 10:03

1 Answers1

4

You need to know which child each node is, and from that you can derive the next node from the structure. You can do that with pointer equality

struct iter_base {
    std::shared_ptr<node> current;
    bool isRoot() const { return !current->_parent.lock(); }
    bool isLeft() const { auto parent = current->_parent.lock(); return parent && (current == parent->_leftChild); }
    bool isRight() const { auto parent = current->_parent.lock(); return parent && (current == parent->_rightChild); }
};

E.g. for inorder:

  • If you have a right child, follow that node's left descendants until there are no more, the last one is the next node.
  • Otherwise, if you are a left child, the next node is your parent.
  • Otherwise, if you are a right child, follow parent pointers until you find one that is a left child, and the next node is the parent of that left child. You've reached the end if you get to the root doing this.
Caleth
  • 52,200
  • 2
  • 44
  • 75
  • That is what I meant. I just suspected that OP forgot to mention an obstacle... – Yunnosch Jun 07 '21 at 09:09
  • as Yunnosch suggests, I guess my question wasn't clear enough.. I was indeed trying to traversal without holding a data-structure of nodes. thanks. that's was really helpful. – Kfir Ettinger Jun 13 '21 at 20:38