数据结构——二叉树前序、中序、后序,三种遍历
1.前序遍历
2.中序遍历
3.后序遍历
(1)前序遍历:访问根结点的操作发生在遍历其左右子树之前。
即:根---------->根节点的左子树------->根节点的右子树
图示展示:
1->2->3->4->5->6
递归实现代码展示:
void PreOrder (BTNode* root)
{
if(NULL==root)
return;
printf("%d",root->data);
PreOrder(root->left);
PreOrder(root->right);
}
分析:
结合代码和图可知:当进入头节点后,如果头节点不为空,则进行下一步操作,首先打印头节点1;然后向左进行递归,每次调用递归前先打印当前的节点,直到最后一个root->left指向为空后,这时候就会回退到上一个节点3,执行(PreOrder(root->right))向右进行递归,当root->right指向空时,这时候就会回退到上一个节点3.这时候的节点3左右都递归完了,就会继续返回到上一个节点2,执行(PreOrder(root->right)),后续操作一样。
递归的代码解释下图所示:
非递归迭代实现代码:
该方法就是用vector来存储得到val,然后创建了一个栈,用栈来实现模拟递归的方法。
class Solution {
public:
vector<int> preorderTraversal(TreeNode* root) {
vector<int> v;
if(nullptr==root)
return v;
TreeNode* cur=root;
stack<TreeNode*>s;
while(cur ||!s.empty())
{
//顺着左侧路径从上往下遍历,并保存所经路径中所遇到的节点
while(cur)
{
v.push_back(cur->val);
s.push(cur);
cur=cur->left;
}
//将最左侧节点以及其左子树全部遍历
//就剩余最左侧节点的右子树没有遍历
cur=s.top()->right;
s.pop();
}
return v;
}
};
(2)中序遍历:访问根结点的操作发生在遍历其左右子树之中(间)
即: 根节点的左子树------->根----->根节点的右子树
如图:
3->2->1->5->4->6
递归实现代码展示:
void InOrder (BTNode* root)
{
if(NULL==root)
return;
InOrder(root->left);
printf("%d",root->data);
InOrder(root->right);
}
其递归方法和上述前序遍历一样,中序遍历就是先递归到最左边的叶子节点然后开始打印,根节点在中间位置打印。
非递归迭代实现代码:
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
vector<int> v;
if(nullptr==root)
return v;
TreeNode* cur=root;
stack<TreeNode*> s;
while(cur ||!s.empty())
{
//找最左侧节点,并保存所有经过路径中的每个节点,目的:模拟递归回退
while(cur)
{
s.push(cur);
cur=cur->left;
}
//cur现在是最左侧节点的左孩子,即cur在空的位置
//相当于cur对应的这颗树已经被遍历完了
cur=s.top();
v.push_back(cur->val);
s.pop();
cur=cur->right;
}
return v;
}
};
(3) 后序遍历:访问根结点的操作发生在遍历其左右子树之后。
即: 根节点的左子树------->根节点的右子树------>根
如图:
3->2->5->6->4->1
递归实现代码展示:
原理同前序遍历一样
void PostOrder (BTNode* root)
{
if(NULL==root)
return;
PostOrder(root->left);
PostOrder(root->right);
printf("%d",root->data);
}
非递归迭代实现代码:
class Solution {
public:
vector<int> postorderTraversal(TreeNode* root) {
vector<int> v;
if(nullptr==root)
return v;
TreeNode* cur=root;
stack<TreeNode*> s;
TreeNode*prev=nullptr; //用来标记刚刚遍历过的节点
while(cur ||!s.empty())
{
//顺着左侧路径找到最左侧节点,并保存所经路径中的所有节点
while(cur)
{
s.push(cur);
cur=cur->left;
}
TreeNode*top=s.top();
if(top->right==nullptr || top->right==prev)
{
v.push_back(top->val);
prev=top; //标记刚刚遍历过的节点
s.pop();
}
else
{
cur=top->right;
}
}
return v;
}
};