【数据结构与算法】力扣:二叉树的前、中、后序遍历

文章详细介绍了如何使用递归和迭代法对二叉树进行前序、中序和后序遍历。递归法中,分别按照根-左-右的顺序进行前序遍历,左-根-右的顺序进行中序遍历,以及左-右-根的顺序进行后序遍历。在迭代法中,利用栈来模拟递归过程,尤其在后序遍历中需要对结果数组进行反转。
摘要由CSDN通过智能技术生成

递归法

前序遍历

给你二叉树的根节点 root ,返回它节点值的前序 遍历。
示例 1:
输入:root = [1,null,2,3]
输出:[1,2,3]
示例 2:
输入:root = []
输出:[]
示例 3:
输入:root = [1]
输出:[1]
示例 4:
输入:root = [1,2]
输出:[1,2]
示例 5:
输入:root = [1,null,2]
输出:[1,2]
提示:
树中节点数目在范围 [0, 100] 内
-100 <= Node.val <= 100
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/binary-tree-preorder-traversal
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

分析

递归:
1.规定递归的函数的参数和返回值
参数:一个指针TreeNode* cur
返回值:结果是一个数组:vector<int>& vec
2.确定终止条件。深度优先搜索,遇到空指针才停止

if(cur == NULL)
return;

3.确定单层递归的逻辑

vec.push(cur->val);//根
traversal(cur->left,vec);//左
traversal(cur->right,vec);//右

代码

/**
 * 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 traversal(TreeNode* cur,vector<int>& vec)//单次遍历的函数
    {
        if(cur == NULL)return;
        vec.push_back(cur->val);
        traversal(cur->left,vec);
        traversal(cur->right,vec);
    }
    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> result;
        traversal(root,result);
        return result;
    }
};

中序遍历

代码

/**
 * 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 traversal(TreeNode* cur,vector<int>& vec)
    {
        if(cur == NULL)
        {
         return;
        }
        traversal(cur->left,vec);
        vec.push_back(cur->val);
        traversal(cur->right,vec);
    }
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> result;
        traversal(root,result);
        return result;
    }
};

后序遍历

/**
 * 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 traversal(TreeNode* cur,vector<int>& vec)
    {
        if(cur == NULL)return;
        traversal(cur->left,vec);
        traversal(cur->right,vec);
        vec.push_back(cur->val);
    }
    vector<int> postorderTraversal(TreeNode* root) {
        vector<int> result;
        traversal(root,result);
        return result;

    }
};

迭代法

前序遍历(根左右)

【分析】编程语言中,常用“栈”来实现递归,用迭代法模拟递归也用栈。

在这里插入图片描述

代码

/**
 * 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:
    vector<int> preorderTraversal(TreeNode* root) {
        stack<TreeNode*> st;//定义一个栈保存树中的结点
        vector<int> res;
        if(root == NULL) return res;
        st.push(root);//先把根结点放入栈中
        while(!st.empty())
        {
            TreeNode* node = st.top();//树的根节点就是栈顶元素
            st.pop();//将当前栈顶元素弹出
            res.push_back(node->val);
            if(node->right)st.push(node->right);//将栈顶元素的右孩子入栈
            if(node->left)st.push(node->left);//将栈顶元素的左孩子入栈
        }
        //一遍遍历结束,到了左子树的根节点,即上一个结点的左孩子,即此时栈的栈顶元素
        return res;

    }
};

后序遍历(左右根)

上文中前序遍历的顺序是:中->左->右
改为:中->右->左
再翻转数组:左->右->中

代码

/**
 * 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:
    vector<int> postorderTraversal(TreeNode* root) {
        stack<TreeNode*> st;
        vector<int> res;
        //vector<int> rres;
        if(root == NULL)return res;
        st.push(root);
        while(!st.empty())
        {
            TreeNode* node = st.top();
            st.pop();
            res.push_back(node->val);
            if(node->left) st.push(node->left);
            if(node->right) st.push(node->right);
        }
      reverse(res.begin(),res.end());
        return res;
    }
};

中序遍历

在这里插入图片描述
左孩子为空将栈顶元素加到数组里;右孩子为空,弹出栈顶元素。

模拟例子中的步骤

  • 从根节点开始向左遍历。根节点为5
cur = root;
  • 一直到遍历到最左端,一路向左,将指针经过的所有左结点放入栈中,直到再无左结点可遍历时停止。当栈为空时,也停止遍历。将5、4、1依次放入栈中
while(cur!=NULL || !st.empty())
{
	if(cur != NULL)
	{
		st.push(cur);
		cur = cur->left;
	}
  • 访问到最左端结点1,1没有左孩子了。取栈顶结点1(即最近访问过的结点),将其弹出栈,加入到数组(加入到数组的结点都是要处理的),遍历此时取出来的栈顶结点1的右孩子
else
{
	cur = st.top();
	st.pop();
	res.push_back(cur->val);
	cur = cur->right;
}
}
  • 结点1的右孩子也为空,执行的还是else分支,即弹出栈顶元素,此时栈顶元素为4,将4加入数组,处理结点4,4的右孩子为2
  • 此时cur->val=2,执行if分支,将2加入栈中
  • 执发现2的左孩子为空,执行else,弹出栈顶元素2,并加入数组,发现2的右孩子也为空
  • 执行else取此时栈顶元素5,将5加入数组,取5的右孩子6
  • 执行if将6入栈并发现6无左孩子,执行else,将6弹出栈,最终栈空,循环停止,程序结束
    对于第一遍遍历就存在栈中的元素,取出来放到数组中时要做的操作的只有访问右节点,但是若其含有右节点则需要将其右节点从头执行循环,要新加入栈中。即对于不是第一遍遍历就在栈中的节点,会多了个if操作

代码

/**
 * 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:
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> res;
        stack<TreeNode*> st;
        TreeNode* cur = root;
        while(cur!=NULL || !st.empty())
        {
            if(cur!=NULL)
            {
                st.push(cur);//如果访问到的元素不为空 就把它记录到栈里 即记录指针指过的元素
                cur = cur->left;//指针一路向左
            }
            //遇到了空结点
            else
            {
                cur = st.top();//记录最近访问过的结点 即栈顶元素
                st.pop();//将其弹出栈 放入数组
                res.push_back(cur->val);
                cur = cur->right;//遍历当前指针的右孩子
                }
            }
            return res;
            }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值