【问题标题】:Cause of Infinite Loop? (iterative inorder traversal implementation) C++无限循环的原因? (迭代中序遍历实现)C++
【发布时间】:2020-08-05 04:40:04
【问题描述】:

问题:迭代地实现中序遍历。

我的尝试:(导致我无法调试的无限循环)非常感谢任何帮助或建议

/**
 * 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;
            
        }
};

编辑:我没有TreeNode的具体内部定义,但是如果你想运行问题,结帐:https://leetcode.com/problems/binary-tree-inorder-traversal/

【问题讨论】:

    标签: c++ algorithm traversal inorder


    【解决方案1】:

    问题来了:

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

    您正在推入堆栈(然后dfs.top() 将更改),然后在下一行访问dfs.top()-&gt;left

    【讨论】:

      【解决方案2】:

      你在这里修改第一行的栈

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

      您想要做的是将之前的dfs.top()-&gt;left 标记为已访问,但是您在堆栈顶部添加了更多元素,因此新的dfs.top() 是不同的。

      要解决此问题,您应该使用将之前的 dfs.top()-&gt;left 存储在不同的变量中。

      作为最佳实践,您正在处理的变量或对象应该是不可变的,因为堆栈不是不可变的,请勿在插入其中或进行其他计算时使用其top。而是将所需的变量存储到像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});
          }
        }
      

      【讨论】:

        【解决方案3】:

        只需要2个简单的规则就可以实现一个迭代的中序遍历。

        如果你在节点 X,那么:

        1. 如果 X 有一个右孩子,则移动到右孩子,并沿着尽可能多的左链接找到下一个节点。
        2. 否则,在右边找到 X 的最近祖先,即左子树包含 X 的最近祖先。如果没有这样的祖先,那么你就完成了。

        如果您的树没有父链接,那么您将需要一个堆栈来存储正确的祖先,但不需要访问集:

        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;
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2023-03-17
          • 2013-03-19
          • 2020-08-20
          • 2014-03-22
          • 2019-07-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多