Search code examples
pythontreerpn

Height of RPN Tree with Binary and Unary Nodes


I know there is a way to get the depth of a pure binary RPN tree (e.g. here), but I am struggling to find out how to get the depth of a tree with binary and unary nodes.

For this problem, I am for the moment considering the following tokens: a set of binary operators '+', '-', '*', a set of unary operators 'cos', 'exp', and the leaf node 'x'. I have deduced that the tree I seek can have at most depth - 1 binary node, depth leaves and 0 unary nodes, or, at the other extreme, depth unary nodes, 0 binary nodes and 1 leaf node. Furthermore, I find that the number of leaves seems to always be the number of binary nodes + 1 in a valid RPN expression for my setting. However, I don't think this is a useful criterion for solving my problem, since simply changing the order of tokens can completely change the depth...

Nevertheless, I need to know the depth of an RPN expression with unary and binary nodes. As a bonus, it would be nice to know, if the RPN expression is incomplete (meaning it needs additional nodes added at the end to be complete) what the minimum depth at which the expression can be completed is.


Solution

  • First on your statement:

    I have deduced that the tree I seek can have at most depth - 1 binary node, depth leaves

    This is a mistake. Those maxima should be 2depth−1 internal binary nodes, and 2depth leaves.

    The code you referenced can be easily extended to support unary operations. The principle is the same: a binary operator adds a root node whose height is determined by the highest subtree below it. As a unary operation has only one child tree below it, it is the highest, so no max is needed, and we can write stack.append(stack.pop() + 1) which really simplifies to stack[-1] += 1

    def getRPNdepth(expression):
        stack = []
        for val in expression:
            if val in ['-', '+', '*', '/']:  # all binary operators
                stack.append(max(stack.pop(), stack.pop()) + 1)
            elif val in ['cos', 'exp']:  # all unary operators
                stack[-1] += 1
            else:  # an operand (x)
                stack.append(1)  
        return stack.pop()
    

    Note that if the stack has more than one element before executing return stack.pop(), then the input expression is incomplete. If you want to know what the minimum height would be if the expression were completed, then repeat the action for a binary operator as many times as needed to end up with one item on the stack:

        while len(stack) > 1:
            stack.append(max(stack.pop(), stack.pop()) + 1)
            
        return stack.pop()