代码随想录中给出了二叉树非递归统一遍历方法,原文认为
但是统一风格的迭代法并不好理解,而且想在面试直接写出来还有难度的,因此没有给出思路说明。
个人分析
递归时中序遍历二叉树是先遍历左子树到底,然后访问叶子节点,再遍历叶子节点父节点的右子树。 统一遍历,那就是要把访问节点和访问左右子树先后的顺序和递归法保持一致。
trvel(node->left);
node->val;
trvel(node->right);
这里关键节点是:如何判断到了子树底部?
...
while(!st.empty()) {
TreeNode *node = st.top();
if (node != nullptr) { // 非标记,继续遍历
st.pop();
if (node->right) { st.push(node->right); } // 对应2
st.push(node); st.push(nullptr); // 对应1,
if (node->left) { st.push(node->left);} // 对应2
}
else {
st.pop(); // 对应3
node = st.top(); // 对应3
result.emplace_back(node->val); // 对应3
st.pop();
}
}
...
代码随想录给的代码是这样通过nullptr标记实现的:
- 遍历到节点时,一律在节点进栈后加nullptr进栈作为标记,而节点的空子树(nullptr)不进栈;
graph TD;
subgraph Stack
direction LR;
A((N1)) --> A1((N2))-->B((leaf))
end
- 当访问到了左右子树均为nullptr的叶子节点时,该叶子节点进栈顶了,在下一轮迭代时会被再次入栈并加nullptr标记;
graph TD;
subgraph Stack
direction LR;
A((N1)) --> A1((N2)) --> B((leaf))-->C((nullptr))
end
3.出现nullptr标记就开始提取节点的元素了
graph TD;
subgraph Stack
direction LR;
A((N1)) --> A1((N2))
end
graph TD;
subgraph Stack
direction LR;
A((N1)) --> A1((N2)) --> L1((nullptr))
end
graph TD;
subgraph Stack
direction LR;
A((N1)) --> A1((nullptr))
end