1.递归遍历二叉树
1.前序
void traversal(vector<int>& res, TreeNode* root)
{
if (root == nullptr) return;
res.push_back(root->val);
traversal(res, root->left);
traversal(res, root->right);
}
vector<int> preorderTraversal(TreeNode* root) {
vector<int> res;
traversal(res, root);
return res;
}
2.后序
void traversal(vector<int>& res, TreeNode* root)
{
if (root == nullptr) return;
traversal(res, root->left);
traversal(res, root->right);
res.push_back(root->val);
}
3.中序
void traversal(vector<int>& res, TreeNode* root)
{
if (root == nullptr) return;
traversal(res, root->left);
res.push_back(root->val);
traversal(res, root->right);
}
2.迭代遍历二叉树
用迭代的话我们就需要考虑怎么实现的问题了,这时我们往往需要栈来辅助
1.前序
前序遍历情况下,我们以中左右遍历。
针对一个结点,以右左中的顺序入栈,随后出栈就是中左右的顺序,结点出栈时将其右左再入栈,循环直至栈空
vector<int> preorderTraversal(TreeNode* root) {
vector<int> res;
if (root == nullptr) return res;
stack<TreeNode*> s;
s.push(root);
while (!s.empty())
{
//中结点出栈
TreeNode* cur = s.top();
s.pop();
//按照右左入栈,等到出栈时就是反过来的
if (cur->right) s.push(cur->right);
if (cur->left) s.push(cur->left);
res.push_back(cur->val);
}
return res;
}
2.后序
后序遍历是左右中,翻转后是中右左,所以我们只需要把前序遍历的左右调换,最后再翻转一下即可
3.中序
中序比较复杂,中序的结点顺序是左中右
针对一个树,需要以左子树,根节点,右子树的方式去处理
对于它的左子树也是一样,直到子树没有左子树,也就是到了最左下角的结点。
在这个过程中,我们不断将有左子树的结点入栈,来记录未来处理的结点。
总结,对于一个结点,如果它有左子树,将其入栈;没有左子树,则将其出栈,并将其右子树入栈(没有就不用了)。
怎么知道树是否完全遍历完?就是当栈空且我们遍历到空时。若只是栈空,可能是整棵树左子树遍历完了该右子树,若只是指针为空,那可能是因为没有左子树了
vector<int> inorderTraversal(TreeNode* root) {
vector<int> res;
stack<TreeNode*> st;
TreeNode* cur = root;
while (cur != nullptr || !st.empty())
{
//若有左子树,则找到最左下角
while (cur != nullptr)
{
st.push(cur);
cur = cur->left;
}
cur = st.top();
st.pop();
res.push_back(cur->val);
cur = cur->right;
}
return res;
}
3.统一迭代遍历二叉树
对于二叉树,其实我们最头疼就是怎么样知道这个点这次是不是该弹出了,于是我们有了标记法。
当我们访问过这个结点之后,我们在其重新入栈时顺带加入一个nullptr,表示下次再碰到的时候就要出栈。
举个例子:前序遍历是中左右,那么从根节点开始就应当是右中左顺序入栈
对于下图就是,我们访问A,然后栈中放入C B AN。下一次访问栈时,发现是AN,将其出栈即可
同理,中序的话栈中放入C AN B,那么就会先处理B的内容,等到访问到AN,它依然是正常出栈
仍然同理,后序遍历则是放入AN C B。
这个方法下,没遍历完的话栈不会为空,所以判断条件就是栈是否为空
1.前序
vector<int> preorderTraversal(TreeNode* root) {
vector<int> res;
stack<TreeNode*> st;
if (root != nullptr) st.push(root);
while (!st.empty())
{
TreeNode* cur = st.top();
st.pop();
if (cur != nullptr)
{
if (cur->right) st.push(cur->right);
if (cur->left) st.push(cur->left);
st.push(cur);
st.push(nullptr);
}
else
{
res.push_back(st.top()->val);
st.pop();
}
}
return res;
}
2.中序
vector<int> inorderTraversal(TreeNode* root) {
vector<int> res;
stack<TreeNode*> st;
if (root != nullptr) st.push(root);
while (!st.empty())
{
TreeNode* cur = st.top();
st.pop();
if (cur != nullptr)
{
if (cur->right) st.push(cur->right);
st.push(cur);
st.push(nullptr);
if (cur->left) st.push(cur->left);
}
else
{
res.push_back(st.top()->val);
st.pop();
}
}
return res;
}
3.后序
vector<int> postorderTraversal(TreeNode* root) {
vector<int> res;
stack<TreeNode*> st;
if (root != nullptr) st.push(root);
while (!st.empty())
{
TreeNode* cur = st.top();
st.pop();
if (cur != nullptr)
{
st.push(cur);
st.push(nullptr);
if (cur->right) st.push(cur->right);
if (cur->left) st.push(cur->left);
}
else
{
res.push_back(st.top()->val);
st.pop();
}
}
return res;
}