二叉树的前序、中序、后序的递归遍历及迭代遍历
最近复习二叉树时,又复习到了二叉树的经典问题:前序、中序、后序遍历。所以写这篇blog记录自己的心得体会,也分享出来供大家学习参考。
首先要明确一点,前、中、后序的遍历方式有什么不同:这里前中后,其实指的就是中间节点的遍历顺序,只要大家记住前中后序指的就是中间节点的位置就可以了。
看如下中间节点的顺序,就可以发现,中间节点的顺序就是所谓的遍历方式:
- 前序遍历:中左右
- 中序遍历:左中右
- 后序遍历:左右中
下面给大家带来递归的前序、中序、后序遍历方式:
递归前序遍历:
void traversal(TreeNode* root, vector<int>res)
{
if(root == NULL) return; //节点为空直接返回
res.push_back(root -> val);
traversal(root -> left); //左节点
traversal(root -> right);//右节点
}
递归中序遍历:
void traversal(TreeNode* root, vector<int>res)
{
if(root == NULL) return; //节点为空直接返回
traversal(root -> left); //左节点
res.push_back(root -> val); //中间节点
traversal(root -> right);//右节点
}
递归后序遍历:
void traversal(TreeNode* root, vector<int>res)
{
if(root == NULL) return; //节点为空直接返回
traversal(root -> left); //左节点
traversal(root -> right);//右节点
res.push_back(root -> val); //中间节点
}
通过上述三段代码,我们可以发现二叉树的前序、中序、后序遍历代码都十分简洁,且十分相似,只需要改变函数内部语句顺序,就可完成转换。所以递归方法十分简洁易懂,适合初学者记忆。
下面来介绍这三种遍历方式的迭代方式:
迭代前序遍历:
vector<int> preorderTraversal(TreeNode* root) {
vector<int>res;
if(root == nullptr) return res;
stack<TreeNode*>stk;//新建一个栈,来存储TreeNode*
stk.push(root);
while(!stk.empty())
{
TreeNode* cur = stk.top();
stk.pop();
res.push_back(cur -> val);
if(cur -> right) //因为遍历顺序是中左右,所以最后遍历的右节点要先入栈
stk.push(cur -> right);
if(cur -> left)
stk.push(cur -> left);
}
return res;
}
迭代中序遍历:
vector<int> inorderTraversal(TreeNode* root) {
vector<int>res;
stack<TreeNode*>stk;
if(root == nullptr) return res;
TreeNode* cur = root;
while(cur!= nullptr || !stk.empty())
{
if(cur != nullptr) // 指针来访问节点,访问到最底层
{
stk.push(cur); //将访问到的节点进栈
cur = cur -> left; // 左
}
else
{
cur = stk.top(); //弹出数据,放入res中
stk.pop();
res.push_back(cur -> val); // 中
cur = cur -> right; // 右
}
}
return res;
}
迭代后序遍历:
vector<int> postorderTraversal(TreeNode* root) {
vector<int>res;
if(root == nullptr) return res;
stack<TreeNode*>stk;
stk.push(root); // 与前序遍历相同
while(!stk.empty())
{
TreeNode* cur = stk.top();
stk.pop();
res.push_back(cur -> val);
if(cur -> left) //可以先转换为中右左,最后通过reverse转换为后序遍历左右中
stk.push(cur -> left); //左节点最后遍历,先入栈
if(cur -> right)
stk.push(cur -> right);
}
reverse(res.begin(), res.end());
return res;
}
从上述三段代码,我们可以看出,迭代前序和后序遍历类似,只需用到栈,而中序遍历特殊,不仅用到了栈还用到了指针,这需要特别注意!
最后,希望这篇文章能给大家带来帮助!