7

Can anyone give me a solution for traversing a binary tree in inorder without recursion and without using a stack?

Gautham
  • 3,418
  • 3
  • 30
  • 41

6 Answers6

5

Second edit: I think this is right. Requires node.isRoot, node.isLeftChild, and node.parent, in addition to the usual node.left_child and node.right_child.

state = "from_parent"
current_node = root
while (!done)
  switch (state)
    case "from_parent":
      if current_node.left_child.exists
        current_node = current_node.left_child
        state = "from_parent"
      else
        state = "return_from_left_child"
    case "return_from_left_child"
      if current_node.right_child.exists
        current_node = current_node.right_child
        state = "from_parent"
      else
        state = "return_from_right_child"
    case "return_from_right_child"
      if current_node.isRoot
        done = true
      else
        if current_node.isLeftChild
         state = "return_from_left_child"
        else
         state = "return_from_right_child"
        current_node = current_node.parent
mbeckish
  • 10,485
  • 5
  • 30
  • 55
  • 3
    I'm fairly certain this is going to have problems with trees of depth > 2. – Daniel Spiewak Apr 07 '10 at 19:04
  • You beat me to it. But note that this works only if the field node.parent exists, that is if the node knows its parent. This is permitted, but not required, by the definition of a binary tree. – Beta Apr 07 '10 at 19:04
  • 1
    If you have node.parent, you don't need node.isRoot. Also, I think you can do without node.isLeftChild. – Beta Apr 07 '10 at 20:07
  • @mbeckish incredible especially if this came right from the top of your head – Bazooka Jan 27 '12 at 12:30
1

1. Double threaded tree

If your tree nodes have parent references/pointers, then keep track of which you node you came from during the traversal, so you can decide where to go next.

In Python:

class Node:
    def __init__(self, value, left=None, right=None):
        self.value = value
        self.left = left
        self.right = right
        self.parent = None
        if self.left:
            self.left.parent = self
        if self.right:
            self.right.parent = self

    def inorder(self):
        cur = self
        pre = None
        nex = None
        while cur:
            if cur.right and pre == cur.right:
                nex = cur.parent
            elif not cur.left or pre == cur.left:
                yield cur.value  # visit!
                nex = cur.right or cur.parent
            else:
                nex = cur.left
            pre = cur
            cur = nex

root = Node(1,
            Node(2, Node(4), Node(5)),
            Node(3)
        )

print([value for value in root.inorder()])  # [4, 2, 5, 1, 3]

2. Single threaded tree

If your tree nodes do not have parent references/pointers, then you can do a so-called Morris traversal, which temporarily mutates the tree, making the right property -- of a node that has no right child -- temporarily point to its inorder successor node:

In Python:

class Node:
    def __init__(self, value, left=None, right=None):
        self.value = value
        self.left = left
        self.right = right

    def inorder(self):
        cur = self
        while cur:
            if cur.left:
                pre = cur.left
                while pre.right:
                    if pre.right is cur:
                        # We detect our mutation. So we finished
                        # the left subtree traversal.
                        pre.right = None
                        break
                    pre = pre.right
                else:  # prev.right is None
                    # Mutate this node, so it links to curr
                    pre.right = cur
                    cur = cur.left
                    continue
            yield cur.value
            cur = cur.right

root = Node(1,
            Node(2, Node(4), Node(5)),
            Node(3)
        )

print([value for value in root.inorder()])
trincot
  • 317,000
  • 35
  • 244
  • 286
0

Start with tree_first(), continue with tree_next() until get NULL. Full code: https://github.com/virtan/tree_closest

struct node {
    int value;
    node *left;
    node *right;
    node *parent;
};

node *tree_first(node *root) {
    while(root && root->left)
        root = root->left;
    return root;
}

node *tree_next(node *p) {
    if(p->right)
        return tree_first(p->right);
    while(p->parent) {
        if(!p->parent->right || p->parent->right != p)
            return p->parent;
        else p = p->parent;
    }
    return 0;
}
Igor Milyakov
  • 602
  • 5
  • 7
0

Since traversing a binary tree requires some kind of state (nodes to return after visiting successors) which could be provided by stack implied by recursion (or explicit by an array).

The answer is no, you can't. (according to the classic definition)

The closest thing to a binary tree traversal in an iterative way is probably using a heap

EDIT: Or as already shown a threaded binary tree ,

stacker
  • 68,052
  • 28
  • 140
  • 210
0

Yes, you can. In order to do this, you would require a parent pointer in order to ascend the tree.

1337c0d3r
  • 1,604
  • 2
  • 20
  • 15
-1

As someone here already stated, it is possible, but not without the parent pointer. The parent pointer basically allows you to traverse "the path" if you want, and therefore print-out the nodes. But why does recursion works without parent pointer? Well if you understand recursion it goes something like this(imagine the recursion stack):

  recursion //going into
   recursion
    recursion
     recursion 
     recursion //going back up
    recursion
   recursion
  recursion

So when the recursion ends you then have printed the chosen side of the binary tree in reversed order.