一般的中序遍历代码如下:
void inorder(TreeNode * root){
if(!root)return;
bfs(root->left);
cout<<root->val<<" ";
bfs(root->right);
}
但递归会隐式调用栈,有额外的开销。能不能想个办法继续优化空间呢?先看看中序遍历的规律,对于每一个结点,我们是希望先遍历他的前面结点再遍历这个结点。而结点的上一个结点一般都是左子树最右边的结点。故考虑修改前驱结点的右指针,使其指向该结点。
那么就会出现几中情况:
·如果该结点没有左子树,就遍历这个点,然后跳到右子树。
·如果该结点有左子树,则先去寻找他的前驱结点,既左子树最右边的结点。找到后,会有两种情况。
①一般来说第一次找的话这个点不会有右子树的,所以就将该点赋为前驱结点的右子树,然后跳转到该结点的左子树。
②但如果前驱结点的右子树为该点,说明前面已经修改过右子树(通过刚刚说的步骤来修改),此时就该设置右子树为空,遍历该点,再跳到右子树。
注意,修改前驱结点的右子树,然后跳转到该结点左子树之后,后续的循环操作还会再次回到该结点上,此时才会有②情况发生。
代码如下:
TreeNode *cur = root, *pre = nullptr;
while (cur) {
if (!cur->left) {
cout<<cur->val<<" ";
cur = cur->right;
continue;
}
pre = cur->left;
while (pre->right && pre->right != cur) {
pre = pre->right;
}
if (!pre->right) {
pre->right = cur;
cur = cur->left;
} else {
pre->right = nullptr;
cout<<cur->val<<" ";
cur = cur->right;
}
}
思路来自于leetcode。