简体   繁体   English

无限循环的原因? (迭代中序遍历实现)C++

[英]Cause of Infinite Loop? (iterative inorder traversal implementation) C++

Question: Implement Inorder Traversal iteratively.问题:迭代地实现中序遍历。

My Attempt: (results in an infinite loop that I haven't been able to debug) any help or suggestions greatly appreciated我的尝试:(导致我无法调试的无限循环)非常感谢任何帮助或建议

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
#include <vector>
#include <stack>
#include <unordered_set>
using namespace std;

class Solution {
    
    public:
    
        vector<int> inorderTraversal(TreeNode* root) {
            
            //iterative sol:
            vector<int> sol;
            stack<TreeNode*> dfs;
            dfs.push(root);
            unordered_set<TreeNode*> visited;
            visited.insert({root});
            TreeNode* temp;
            
            while (!dfs.empty()) {
                
                if (dfs.top()->left != nullptr && visited.find(dfs.top()->left) == visited.end()) {
                    dfs.push(dfs.top()->left);
                    visited.insert({dfs.top()->left});
                }
                else {
                    sol.push_back(dfs.top()->val);
                    temp = dfs.top();
                    dfs.pop();
                    
                    if (temp->right != nullptr && visited.find(temp->right) == visited.end()) {
                        dfs.push(temp->right);
                        visited.insert({temp->right});
                    }
                }     
                          
            }
            
            return sol;
            
        }
};

EDIT: I don't have the specific internal definitions of the TreeNode, but if you want to run the problem, checkout: https://leetcode.com/problems/binary-tree-inorder-traversal/编辑:我没有 TreeNode 的具体内部定义,但如果你想运行问题,请查看: https://leetcode.com/problems/binary-tree-inorder-traversal/

Here is the problem:这是问题所在:

dfs.push(dfs.top()->left);
visited.insert(dfs.top()->left);

You are pushing to stack (then dfs.top() will change) and then accessing dfs.top()->left in the next line.您正在推入堆栈(然后dfs.top()将更改),然后在下一行访问dfs.top()->left

You are modifying the stack in the first line here您正在此处修改第一行中的堆栈

  dfs.push(dfs.top()->left);
  visited.insert({dfs.top()->left});

what you want to do is to mark the previous dfs.top()->left as visited, but you are adding more element on top of the stack and thus the new dfs.top() is a different one.您要做的是将先前的dfs.top()->left标记为已访问,但是您要在堆栈顶部添加更多元素,因此新的dfs.top()是不同的。

To solve this problem you should use store the previous dfs.top()->left in a different variable.要解决此问题,您应该使用将先前的dfs.top()->left存储在不同的变量中。

As a best practice, the variable or object you are working on should be immutable, since the stack is not immutable don't use its top while inserting into it or doing some other computations.作为最佳实践,您正在处理的变量或 object 应该是不可变的,因为堆栈不是不可变的,因此在插入堆栈或进行其他计算时不要使用它的top Instead store your required variable into something immutatble like temp here而是将您所需的变量存储到像temp这样的不可变变量中

 temp = dfs.top();
 if (temp->left != nullptr && visited.find(temp->left) == visited.end()) {
    dfs.push(temp->left);
    visited.insert({temp->left});
  }
  else {
    sol.push_back(dfs.top()->val);
    dfs.pop();
                    
    if (temp->right != nullptr && visited.find(temp->right) == visited.end()) {
       dfs.push(temp->right);
       visited.insert({temp->right});
    }
  }

It only takes 2 simple rules to implement an iterative in-order traversal.只需要 2 个简单的规则就可以实现一个迭代的中序遍历。

If you're at node X, then:如果您在节点 X,则:

  1. If X has a right child, then move to the right child, and follow as many left links as possible to find the next node.如果 X 有一个右孩子,则移动到右孩子,并沿着尽可能多的左链接找到下一个节点。
  2. Otherwise, find the closest ancestor of X on the right, ie, the closest ancestor whose left subtree contains X. If there is no such ancestor then you're done.否则,在右边找到 X 的最近祖先,即左子树包含 X 的最近祖先。如果没有这样的祖先,那么你就完成了。

If your tree doesn't have parent links, then you'll need a stack to store the right ancestors, but there's no need for a visited set:如果您的树没有父链接,那么您将需要一个堆栈来存储正确的祖先,但不需要访问集:

vector<int> inorderTraversal(TreeNode* tree) {
    vector<int> ret;
    stack<TreeNode *> nextParents;
    for(;tree; tree = tree.left) {
        nextParents.push(tree);
    }
    while(!nextParents.empty()) {
        tree = nextParents.pop();
        ret.push_back(tree->val);
        for(tree = tree.right; tree; tree = tree.left) {
            nextParents.push(tree);
        }
    }
    return ret;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM