Iterating over a Binary Tree with O(1) Auxiliary Space

后端 未结 10 1308
广开言路
广开言路 2020-11-30 04:03

Is it possible to iterate over a binary tree in O(1) auxiliary space (w/o using a stack, queue, etc.), or has this been proven impossible? If it is possible, how can it be

10条回答
  •  猫巷女王i
    2020-11-30 04:59

    You can achieve this if nodes have pointers to their parents. When you walk back up the tree (using the parent pointers) you also pass the node you're coming from. If the node you're coming from is the left child of the node you're now at, then you traverse the right child. Otherwise you walk back up to it's parent.

    EDIT in response to the edit in the question: If you want to iterate through the whole tree, then no this is not possible. In order to climb back up the tree you need to know where to go. However, if you just want to iterate through a single path down the tree then this can be achieved in O(1) additional space. Just iterate down the tree using a while loop, keeping a single pointer to the current node. Continue down the tree until you either find the node you want or hit a leaf node.

    EDIT: Here's code for the first algorithm (check the iterate_constant_space() function and compare to the results of the standard iterate() function):

    #include 
    #include 
    using namespace std;
    
    /* Implementation of a binary search tree. Nodes are ordered by key, but also
     * store some data.
     */
    struct BinarySearchTree {
      int key;      // they key by which nodes are ordered
      string data;  // the data stored in nodes
      BinarySearchTree *parent, *left, *right;   // parent, left and right subtrees
    
      /* Initialise the root
       */
      BinarySearchTree(int k, string d, BinarySearchTree *p = NULL)
        : key(k), data(d), parent(p), left(NULL), right(NULL) {};
      /* Insert some data
       */
      void insert(int k, string d);
      /* Searches for a node with the given key. Returns the corresponding data
       * if found, otherwise returns None."""
       */
      string search(int k);
      void iterate();
      void iterate_constant_space();
      void visit();
    };
    
    void BinarySearchTree::insert(int k, string d) {
      if (k <= key) { // Insert into left subtree
        if (left == NULL)
          // Left subtree doesn't exist yet, create it
          left = new BinarySearchTree(k, d, this);
        else
          // Left subtree exists, insert into it
          left->insert(k, d);
      } else { // Insert into right subtree, similar to above
        if (right == NULL)
          right = new BinarySearchTree(k, d, this);
        else
          right->insert(k, d);
      }
    }
    
    string BinarySearchTree::search(int k) {
      if (k == key) // Key is in this node
        return data;
      else if (k < key && left)   // Key would be in left subtree, which exists
        return left->search(k); // Recursive search
      else if (k > key && right)
        return right->search(k);
      return "NULL";
    }
    
    void BinarySearchTree::visit() {
      printf("Visiting node %d storing data %s\n", key, data.c_str());
    }
    
    void BinarySearchTree::iterate() {
      visit();
      if (left) left->iterate();
      if (right) right->iterate();
    }
    
    void BinarySearchTree::iterate_constant_space() {
      BinarySearchTree *current = this, *from = NULL;
      current->visit();
      while (current != this || from == NULL) {
        while (current->left) {
          current = current->left;
          current->visit();
        }
        if (current->right) {
          current = current->right;
          current->visit();
          continue;
        }
        from = current;
        current = current->parent;
        if (from == current->left) {
          current = current->right;
          current->visit();
        } else {
          while (from != current->left && current != this) {
            from = current;
            current = current->parent;
          }
          if (current == this && from == current->left && current->right) {
            current = current->right;
            current->visit();
          }
        }
      }
    }
    
    int main() {
      BinarySearchTree tree(5, "five");
      tree.insert(7, "seven");
      tree.insert(9, "nine");
      tree.insert(1, "one");
      tree.insert(2, "two");
      printf("%s\n", tree.search(3).c_str());
      printf("%s\n", tree.search(1).c_str());
      printf("%s\n", tree.search(9).c_str());
      // Duplicate keys produce unexpected results
      tree.insert(7, "second seven");
      printf("%s\n", tree.search(7).c_str());
      printf("Normal iteration:\n");
      tree.iterate();
      printf("Constant space iteration:\n");
      tree.iterate_constant_space();
    }
    

提交回复
热议问题