How to convert bottom-up recursive algorithm to iterative stack in JavaScript

前端 未结 4 876
醉梦人生
醉梦人生 2021-01-20 20:00

Given the following algorithm:

4条回答
  •  离开以前
    2021-01-20 20:45

    This is a solution using two stacks.

    Suppose we always compute right child before left child, we need a way to store the result of right child. It's possible to store it on the original stack but it would be complicated since that stack is used to compute left child too. So I use another stack to store those results of right children.

    There are three status:

    • need work -> need to push child onto stack to compute
    • need merge -> wait left&right child to be computed
    • finish work -> all work has been done

    When it sees a node with status finish work, it will check if the next node's status is need merge:

    • if it's not, the current finished node is the right child, push it to the cache stack. And ready to compute left child.
    • if it is, the current finished node is the left child, pop from stack and cache stack to get the root and right child, construct new node and push it back to stack with status finish work

    console.log(JSON.stringify(create(2, 5), null, 2))
    
    function Klass(i, l, r) {
      this.i = i;
      this.l = l;
      this.r = r;
    }
    
    function create(i, growto) {
        var stack = [];
        var cache = [];
    
        stack.push([i, 'need work']);
        while (stack.length && stack[0][1] !== 'finish work') {
            var cur = stack.pop();
            var val = cur[0];
            var status = cur[1];
    
            if (status === 'need work') {
                if (val !== growto) {
                    stack.push([val, 'need merge']);
                    stack.push([val + 1, 'need work']);
                    stack.push([val + 1, 'need work']);
                } else {
                    stack.push([val, 'finish work']);
                }
            } else if (status === 'finish work') {
                if (stack[stack.length - 1][1] !== 'need merge') {
                    cache.push(cur);
                } else {
                    var root = stack.pop()[0];
                    var left = cur[0];
                    var right = cache.pop()[0];
                    stack.push([new Klass(root, left, right), 'finish work']);
                }
            }
        }
    
        return stack.pop()[0];
    }

提交回复
热议问题