起因

邓俊辉的中序遍历二叉树采用了和前序遍历不同的循环检查方式,在前序遍历时使用stack非空检查,而在中序遍历时采用了while1检查。不便于迁移学习。

分析

视频地址:

​https://www.bilibili.com/video/BV1jt4y117KR?p=173​

中序遍历时,根据规律每次进入一颗子树也需要先遍历左侧分支,依次入栈。因此一开始可能写下这样的代码:

    vector<int> inorderTraversal(TreeNode* root) {
vector<int> ret;
if (!root) return ret;
vector<TreeNode *> stack = {root};
while (!stack.empty()) {
auto node = stack.back();
while (node->left) {
stack.push_back(node->left);
node = node->left;
}
node = stack.back();
ret.push_back(node->val);
stack.pop_back();
if (node->right) {
stack.push_back(node->right);
}
}
return ret;


当进入一颗子树时,先遍历左侧分支,左侧遍历到空节点时,访问栈top节点,(左侧没有节点了,该访问当前根),访问完当前根,如果有右子树,把右子树push进入下一轮。

但对于[1,null,2,3,null]的树形结构,在push节点2后,进入以2为根的右子树,再开始遍历左侧分支。但回到2时,又开始了左侧分支遍历,循环不能终止。

因此,需要一个从左侧分支返回当前根节点的标志位。

因此,改写后的代码如下:

    vector<int> inorderTraversal(TreeNode* root) {

vector<int> ret;
if (!root) return ret;
vector<TreeNode *> stack = {root};
int lefthasvisited= 0;
while (!stack.empty()) {
auto node = stack.back();
if (!lefthasvisited) {
while (node->left) {
stack.push_back(node->left);
node = node->left;
}
}
node = stack.back();
ret.push_back(node->val);
stack.pop_back();
lefthasvisited = 1;
if (node->right) {
stack.push_back(node->right);
lefthasvisited = 0;
}


}
return ret;