一、二叉树的前、中、后序遍历基础
文章讲解:代码随想录
视频讲解: 写出二叉树的非递归遍历很难么?(前序和后序)
题目:
给你二叉树的根节点 root
,返回它节点值的 前序 遍历。
给定一个二叉树的根节点 root
,返回 它的 中序 遍历 。
给你一棵二叉树的根节点 root
,返回其节点值的 后序遍历 。
代码:
前序遍历
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
/*void build(TreeNode *node,vector<int>& ans)//确定递归函数的参数和返回值
{
if (node == NULL) return;//确定终止条件
//确定单层递归的逻辑
ans.push_back(node->val);//中
build(node->left, ans);//左
build(node->right, ans);//右
return;
}*/
vector<int> preorderTraversal(TreeNode* root) {
vector<int> ans;
//递归法
//build(root, ans);
//迭代法
stack<TreeNode*> stack;//二叉树深度遍历递归用栈
if (root == NULL) return {};
stack.push(root);
/*while (!stack.empty())
{
TreeNode *node = stack.top();
stack.pop();
ans.push_back(node->val);//中 处理返回数组
if (node->right) stack.push(node->right);//右 先放后弹
if (node->left) stack.push(node->left);//左
}*/
//统一迭代法
while (!stack.empty())
{
root = stack.top();// 指向一个结点确定位置
if (root != NULL)
{
stack.pop();//确定位置的指针并不是要被处理的
if (root->right) stack.push(root->right);//右
if (root->left) stack.push(root->left);//左
stack.push(root);//中
stack.push(NULL); //中的处理标记
}
else//返回数组处理标记
{
stack.pop();
root = stack.top();//及时pop以免忘记
stack.pop();
ans.push_back(root->val);
}
}
return ans;
}
};
后序遍历
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
/*void build(TreeNode *node, vector<int> &ans)
{
if (node == NULL) return;
build(node->left, ans);
build(node->right, ans);
ans.push_back(node->val);
return;
}*/
vector<int> postorderTraversal(TreeNode* root) {
vector<int> ans;
//递归法
//build(root, ans);
//迭代法
stack<TreeNode*> stack;
if (!root) return{};
stack.push(root);
/*while (!stack.empty())
{
TreeNode *node = stack.top();
stack.pop();
ans.push_back(node->val);
if (node->left) stack.push(node->left);
if (node->right) stack.push(node->right);
}
reverse(ans.begin(), ans.end());*///中右左 反转成 左右中
//统一迭代法
while (!stack.empty())
{
root = stack.top();
if (root != NULL)
{
stack.pop();
stack.push(root);
stack.push(NULL);
if (root->right) stack.push(root->right);
if (root->left) stack.push(root->left);
}
else
{
stack.pop();
root = stack.top();
stack.pop();
ans.push_back(root->val);
}
}
return ans;
}
};
中序遍历
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
/*void build(TreeNode *node, vector<int> &ans)
{
if (node == NULL) return;
build(node->left, ans);
ans.push_back(node->val);
build(node->right,ans);
return;
}*/
vector<int> inorderTraversal(TreeNode* root) {
vector<int> ans;
//递归法
//build(root, ans);
//迭代法
stack<TreeNode*> stack;
/*while (root != NULL || !stack.empty())
{
if (root) // 指针确定位置在最底层
{
stack.push(root); // 不断将左侧入栈
root = root->left;
}
else//处理返回数组的标志
{
root = stack.top();
stack.pop();
ans.push_back(root->val); //左即中 中
root = root->right; // 右
}
}*/
//统一迭代法
if (!root) return {};
stack.push(root);
while(!stack.empty())
{
root = stack.top();
if (root != NULL)
{
stack.pop();
if (root->right) stack.push(root->right);
stack.push(root);
stack.push(NULL);
if (root->left) stack.push(root->left);
}
else
{
stack.pop();
root = stack.top();
stack.pop();
ans.push_back(root->val);
}
}
return ans;
}
};
总结:
1.递归法:(1)确定递归函数的参数和返回值 (2)确定终止条件 (3)确定单层递归的逻辑
2.迭代法:(1) 注意左右中的顺序略有不同 (2) 中序遍历的写法与前序遍历不同。前序遍历直接处理根结点,然后将左右压入栈中。中序遍历需用指针往左移到底层,再处理左即中结点,接着指针指向右结点。
3.统一迭代法:(1)将入栈与处理返回数组分开 ,先用指针指向一个结点位置,再执行相应入栈操作,如果达到处理返回数组条件(条件:结点为NULL,注意:在栈中的中后放一个NULL标记), 就处理返回数组。