Trees

I was also asked to traverse a tree in-order without using recursion.
A few days after the interview, I spent a long time trying to figure
out how to do this. Once you see it, it's easy.

First I implemented the recursive version which took about 10 seconds.
The non-recursive version requires you to handle the stack yourself.
The trick is that you can't just back up one node and iterate again.
This will get you stuck in an infinite loop. You have to repeatedly
pop off the stack until you can go right. So, the steps are. (1) Go
left as far as you can (pushing all the way). (2) Go into a loop, popping
and printing until you can go right. (3) Go right. Notice at this
point, the next time you pop, it will be from the node just above the
node where you went right. (4) Repeat.

The reason you don't need to do this with the recursive version is
because you don't always return back to the top of the function as
with the iterative version. With the recursive version, when you
can't go right anymore, the functions will return until you end up back
where you can go right. But this will be after the left in-order
call, not the top of the function.

I also made a brief attempt to use gotos to model how the recursive
version works. I didn't get very far; I think it might require a
second stack to store each right and left call. Then you know whether
to jump back to the top (before the left call) or after the left call.

The other day I had an insight. Go back and think about how the stack
version of the list reversal works. Picture the list next to the
stack. They go in opposite directions. If you combine the two, what
you have is a doubly linked list. In fact, list reversal of a doubly
linked list is trivial. It's already reversed! But it gets better.
If you think about moving back and forth along a list, the only
place you need the two way links is at three pointers: current,
previous, and next. In fact, you can move back and forth along a
singly linked list by just reversing pointers as you go. All that
matters is that you keep a window of three pointers, and you can move
in either direction you want.

NULL<--| |<---| |<---| |--->| |--->| |<--head
next^ curr^ prev^

Now think about a tree. Any path you take through the tree is really
a list (in some sense). A list is a degenerate tree. It should be
possible to use the same idea above to traverse a tree (in-order)
without a stack. And in fact, you can do it. The one minor problem
is that it destroys the tree. (There are also memory leaks, but
that's easy to fix.) So the only way it would be useful is if you no
longer needed the tree.

The reason you can't repair the tree is tricky. (And it took me
forever to understand this.) For the same reason you need to pop back
out to the next available right node in the iterative traversal, you cannot back up
the tree in the same order you came down. You can still back up, but
it requires you to go back out a different way than you came down.
Basically, in the iterative version, you pop your way back out to the
earliest node that allows you to go right. In this version, you point
the current node to that node, effectively creating a stack as you
move down the tree. The trouble is, without another stack, there is
no way (as far as I can see) to correct some of the nodes that were
reversed as you initially came down the tree.