Search code examples
javascriptnode.jsgeneratorbinary-search-treeecmascript-next

How to convert Generator method to an Iterator


I have this recursive generator method which yields the values of a BST in ascending order:

  *inOrder(node){

    if (node === null) {
      return;
    }

    if(node.left){
      yield * this.inOrder(node.left);
    }

    yield node.val;

    if(node.right){
      yield * this.inOrder(node.right);
    }

  }

A recursive generator is quite CPU intensive. I am trying to convert it to an iterator, to better understand what's going on, here is my attempt which is totally incomplete, using an iterative solution:

  [Symbol.iterator]() {

    // iterative solution?
    const queue = [this.rootNode];

    return {
      next(){

        return {
          done: true,
          value: // (last (right-most) value in tree)
        }

      }
    }

  }

I get the feeling an iterative solution to do depth-first search from left-to-right, will require a queue, but not sure. Alternatively, a recursive solution could work where we pass in the root node initially like so:

  [Symbol.iterator](node) {

    // recursive solution 
    return {
      next(){

        return {
          done: true,
          value: // (last (right-most) value in tree)
        }

      }
    }

  }

However, I am not sure how to implement with an iterator, either an iterative or recursive solution. So that's my question, how to take the generator code and use an iterator instead, somehow.


Solution

  • I took @Sachin's answer and evolved it a bit. This is not well-tested, but appears to work:

      [Symbol.iterator]() {
    
        const stack = [];
        let currentNode = this.rootNode;
    
        return {
          next() {
    
            while (currentNode !== null) {
              stack.push(currentNode);
              currentNode = currentNode.left || null;
            }
    
            if (stack.length < 1) {
              return {done: true, value: null};
            }
    
            const node = stack.pop();
            currentNode = node.right || null;
            return {done: false, value: node.val};
    
          }
        };
      }