Leetcode 先序,中序,后序遍历的题目链接:
144. Binary Tree Preorder Traversal
94. Binary Tree Inorder Traversal
145. Binary Tree Postorder Traversal
warning : 已经熟悉了各种遍历方式的含义以及递归实现的请直接跳到 3
1. 简要介绍一下先序,中序,后序遍历的区别:
例如下面这棵树:
它的遍历结果如下:
先序:8 3 1 6 4 7 10 14 13
中序:1 3 4 6 7 8 10 13 14
后序:1 4 7 6 3 13 14 10 8
究其根本,按照 xx 序遍历二叉树,xx指定的就是根结点相对于其左右子树(或子节点)的访问次序,例如中序遍历则是先访问左子树,再访问根结点(根节点的访问次序在中间),最后访问右子树。
2. 递归法实现各种遍历
这里用先序举例,递归实现不同遍历方法需要改变的地方就是
cout << root->val << " "
这句代码的位置。
void preorder_traversal(TreeNode* root)
{
if(root == NULL)
return ;
cout << root->val << " "; // 先访问根结点
preorder_traversal(root->left); // 再遍历左右子树
preorder_traversal(root->right);
}
3. 迭代法实现各种遍历
3.1 先序遍历:
从最简单的开始,先序遍历时先访问根结点,再依次对左右子树进行先序遍历,这里我们需要使用迭代法实现遍历,首先就想到使用栈模拟递归调用过程,每次我们都对以栈顶的节点为根节点的子树进行先序遍历,先序遍历过程就是访问根节点,将右子节点压栈,再将左子节点压栈(注意这里由于栈是先进后出,所以压入顺序和访问顺序相反)。
代码如下:
vector<int> preorderTraversal(TreeNode* root) {
vector<int> ans;
if(root == NULL)
return ans;
stack<TreeNode*> sk;
sk.push(root);
while(!sk.empty()){
TreeNode* curr = sk.top();sk.pop();
ans.push_back(curr->val);
if(curr->right != NULL)
sk.push(curr->right);
if(curr->left != NULL)
sk.push(curr->left);
}
return ans;
}
3.2 后序遍历
和先序遍历的思想非常类似,仍然是用栈模拟递归。
vector<int> postorderTraversal(TreeNode* root) {
vector<int> ans;
stack<int> ans_sk;
if(root == NULL)
return ans;
stack<TreeNode*> sk;
sk.push(root);
while(!sk.empty()){
TreeNode* node = sk.top();sk.pop();
ans_sk.push(node->val);
if(node->left != NULL)
sk.push(node->left);
if(node->right != NULL)
sk.push(node->right);
}
while(!ans_sk.empty()){
ans.push_back(ans_sk.top());
ans_sk.pop();
}
return ans;
}
3.3 中序遍历
中序遍历稍微特殊一些,回想一下中序遍历的过程,先遍历左子树,再访问根节点,再遍历右子树,由于对根节点的访问处于中间,不能再像先序和后序那样先访问根节点再将其左右子节点压栈,这里我们采用的解决方法是仍然使用栈模拟这个过程,但是处理方式略有不同,比如我们现在中序遍历一棵树,第一次访问到根节点时我们并不能将它的值直接输出到结果数组中,因为根节点的左子树还没被遍历。我们这里采用的解决方式是,第一次遇到根节点时,记录下根节点的左右子节点,先将右子节点压栈,再将根节点的左右子节点指针置空(这里是想标记下当前这个节点已经被访问过一次),然后将子节点的左子节点压栈,弹栈时如果遇到一个左右子节点都为空的节点,则标志着该节点已经被访问过一次,此时就可以将它的值输出到结果数组中了。
代码如下:
vector<int> inorderTraversal(TreeNode* root) {
vector<int> ans;
if(root == NULL)
return ans;
stack<TreeNode*> sk;
sk.push(root);
while(!sk.empty()){
TreeNode* node = sk.top();sk.pop();
if(node->left == NULL && node->right == NULL)
ans.push_back(node->val);
else{
TreeNode* leftChild = node->left;
TreeNode* rightChild = node->right;
node->left = node->right = NULL;
if(rightChild != NULL)
sk.push(rightChild);
sk.push(node);
if(leftChild != NULL)
sk.push(leftChild);
}
}
return ans;
}