无限循环的原因? (迭代中序遍历实现)C++
Cause of Infinite Loop? (iterative inorder traversal implementation) C++
问题:迭代实现中序遍历。
我的尝试:(导致我无法调试的无限循环)非常感谢任何帮助或建议
/**
* 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/
这是问题所在:
dfs.push(dfs.top()->left);
visited.insert(dfs.top()->left);
你正在压栈(然后 dfs.top()
会改变)然后在下一行访问 dfs.top()->left
。
只需要2条简单的规则就可以实现迭代in-order遍历。
如果您在节点 X,则:
- 如果 X 有右 child,则向右移动 child,并尽可能多地沿着左侧链接找到下一个节点。
- 否则,在右边找到X最近的祖先,即左子树中包含X的最近的祖先。如果没有这样的祖先,那么你就完成了。
如果您的树没有 parent 个链接,那么您将需要一个堆栈来存储正确的祖先,但不需要访问集:
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;
}
您正在修改此处第一行的堆栈
dfs.push(dfs.top()->left);
visited.insert({dfs.top()->left});
您想做的是将前一个 dfs.top()->left
标记为已访问,但是您在堆栈顶部添加了更多元素,因此新的 dfs.top()
是一个不同的元素。
要解决此问题,您应该使用将之前的 dfs.top()->left
存储在不同的变量中。
作为最佳实践,您正在处理的变量或对象应该是不可变的,因为堆栈不是不可变的,请勿在插入或进行其他计算时使用其 top
。而是将您需要的变量存储到像 temp
here
这样的不变的东西中
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});
}
}
问题:迭代实现中序遍历。
我的尝试:(导致我无法调试的无限循环)非常感谢任何帮助或建议
/**
* 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/
这是问题所在:
dfs.push(dfs.top()->left);
visited.insert(dfs.top()->left);
你正在压栈(然后 dfs.top()
会改变)然后在下一行访问 dfs.top()->left
。
只需要2条简单的规则就可以实现迭代in-order遍历。
如果您在节点 X,则:
- 如果 X 有右 child,则向右移动 child,并尽可能多地沿着左侧链接找到下一个节点。
- 否则,在右边找到X最近的祖先,即左子树中包含X的最近的祖先。如果没有这样的祖先,那么你就完成了。
如果您的树没有 parent 个链接,那么您将需要一个堆栈来存储正确的祖先,但不需要访问集:
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;
}
您正在修改此处第一行的堆栈
dfs.push(dfs.top()->left);
visited.insert({dfs.top()->left});
您想做的是将前一个 dfs.top()->left
标记为已访问,但是您在堆栈顶部添加了更多元素,因此新的 dfs.top()
是一个不同的元素。
要解决此问题,您应该使用将之前的 dfs.top()->left
存储在不同的变量中。
作为最佳实践,您正在处理的变量或对象应该是不可变的,因为堆栈不是不可变的,请勿在插入或进行其他计算时使用其 top
。而是将您需要的变量存储到像 temp
here
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});
}
}