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

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

Given the following algorithm:

4条回答
  •  我在风中等你
    2021-01-20 20:40

    It's not trivial to mechanically transform any recursive code into a stack machine. Automatic stateful transformations produce very complex code, just think of C#-s or BabelJS-s generators. But sure, it can be done, but you will need mutable stackframes and/or registers. Let's see the problems we are facing:

    How does the machine remember where to continue the execution of a function?

    We have to store some state variable/instruction pointer on the stack itself. This is what you are emulating with the "open" and "close" markers.

    Where to put the result of a function?

    There are many ways:

    • storing it in a temporary register
    • passing the function a reference to a field (an (object, fieldname) pair), emulating out parameters
    • using a second stack like @CtheSky did

    Using mutable stack frames and a result register the transformed code would look something like this:

    console.log(JSON.stringify(create(0), null, 2))
    
    function Klass(i, l, r) {
      this.i = i
      this.l = l
      this.r = r
    }
    
    function Frame(i) {
      this.ip = 0;
      this.i = i;
      this.left = null;
    }
    
    function create(i) {
      var result;
      var stack = [new Frame(i)];
      while (stack.length > 0) {
        var frame = stack[stack.length - 1];
        switch (frame.ip) {
          case 0:
            if (frame.i === 5) {
              result = undefined;
              stack.pop();
              break;
            }
            stack.push(new Frame(frame.i + 1));
            frame.ip = 1;
            break;
          case 1:
            frame.left = result;
            stack.push(new Frame(frame.i + 1));
            frame.ip = 2;
            break;
          case 2:
            result = new Klass(frame.i, frame.left, result);
            stack.pop();
            break;
        }
      }
      return result;
    }

提交回复
热议问题