I want to convert a function that uses recursion to an iterative algorithm.
I have already looked at several explanations on how to switch from one to the other but most of them are limited to easy cases, like factorial, where the recursive function calls itself only once.
In my case I'm working on a function that checks whether two trees are isomorphic:
- Two trees are isomorphic if one tree can be obtained from other by performing any number of flips, i.e. by swapping a node's left subtree with its right subtree, and doing this for any number of nodes, regardless of the different values of the nodes.
An example of isomorphic trees:
Here is the recursive version, where the number of recursive calls becomes exponential:
bool isIsomorphic(node* n1, node *n2){
if (n1 == NULL && n2 == NULL)
return true;
if (n1 == NULL || n2 == NULL)
return false;
return
(isIsomorphic(n1->left,n2->left) && isIsomorphic(n1->right,n2->right))||
(isIsomorphic(n1->left,n2->right) && isIsomorphic(n1->right,n2->left));
}
How can I write this as an iterative algorithm?

When looking at the expression that makes recursive calls, we can see there are different states in which the recursive call is launched:
If we use an integer for enumerating states, we'll just need 4 intermediate states (not counting success/failure). We can picture the transitions as follows:
The pairs indicate which children are combined for a recursive call. A left side branch indicates the analysed subtrees are not isomorphic, while the right side branch indicates they are.
In the stack-based solution you could therefore add the state to the stacked item, so that when you backtrack with either success or failure, you can find out what the resulting state should be:
Here is an implementation of the stack we would need (in C):
And here is the code for the
isomophicfunction itself:Remark
The original recursive algorithm is not optimal, because if the first recursive call returns true, while the second not, then it is impossible that the alternative two recursive calls (on the second line) would both return true. So actually, the recursive version could better be:
This means there are no cases anymore where four recursive calls are needed in the same execution context.
The iterative function would need to be adapted accordingly, so that failure coming back to a state-3 node leads to failure on that node as well (the loop must continue):