二叉树的前序遍历问题的具体思路 递归法 迭代法(附完整代码)


前言

本文将主要围绕以下问题进行讨论:

二叉树的前序遍历。

本文将分别以两种方法【递归】【迭代】来解决这一问题(文章末尾附完整代码)


一、如何理解前序遍历?

二叉树的前序遍历是一种常见的遍历方式,主要按照 “根节点 - 左子树 - 右子树” 的顺序访问二叉树的每个节点。

如下:

       1
     /   \
    2     3
   / \   / \
  4   5 6   7

首先访问根节点 1

遍历左子树:
接着递归地对根节点的左子树进行前序遍历。
在上面的例子中,先访问根节点 1 后,接着对以节点 2 为根的左子树进行前序遍历。首先访问节点 2,然后访问节点 2 的左子节点 4,再访问节点 2 的右子节点 5。

遍历右子树:
当左子树遍历完成后,递归地对根节点的右子树进行前序遍历。
在例子中,左子树遍历完后,对以节点 3 为根的右子树进行前序遍历。首先访问节点 3,然后访问节点 3 的左子节点 6,再访问节点 3 的右子节点 7。

题目链接: [点击跳转] Leetcode 144. 二叉树的前序遍历

请添加图片描述

二、方法一(递归法)

递归法通过深度优先搜索,将二叉树的所有节点全部按照前序的方式遍历出来。

根据示例所给出的输出格式,我们需要定义一个vector类型的变量,并且在最后输出这个变量。同时,我们还应注意到,如果将空节点传入递归函数这种,应该返回一个空值。

代码如下:

vector<int> tre;
void preOrder(TreeNode *root) {
    if (root == nullptr) {
        return;
    }
}

这个时候,我们就可以根据前序的“根-左-右”原则进行排序和递归啦!

vector<int> tre;
void preOrder(TreeNode *root) {
    if (root == nullptr) {
        return;
    }
    tre.push_back(root->val);
    preOrder(root->left);
    preOrder(root->right);
}

完整代码如下:

/**
 * 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> tre;
    void preOrder(TreeNode *root) {
        if (root == nullptr) {
            return;
        }
        tre.push_back(root->val);
        preOrder(root->left);
        preOrder(root->right);
    }

    vector<int> preorderTraversal(TreeNode *root) {
        preOrder(root);
        return tre;
    }
};

时间复杂度为O(n)。


三、方法二(迭代法)

采用了迭代的方式实现前序遍历,借助栈来保存已经访问过的节点,以便在遍历完左子树后能够回到父节点并继续遍历右子树。

通过不断地将当前节点压入栈并更新为其左子节点,直到左子树为空,然后从栈中弹出节点并更新为其右子节点,实现了前序遍历的顺序。

如下代码可以实现前序遍历,并且已标注好每句的作用:

vector<int> tre;
stack<TreeNode*> sta;//建栈
vector<int> preorderTraversal(TreeNode* root) {     
    if (root == nullptr) {//对传入的根节点先做一个判断
        return tre;
    }
    while (!sta.empty() || root != nullptr) {//栈不为空,或者节点不为空时,都将进入下面的循环
        while (root != nullptr) {//当节点还没遍历到树的末端时
            tre.push_back(root->val);//将节点值传入
            sta.push(root);//将该节点压入栈中
            root = root->left;//指向左子节点
        }
        root = sta.top();//取栈顶元素
        sta.pop();//出栈
        root = root->right;//指向右子节点
    }
    return tre;
}

在循环内部有一个嵌套的while循环,这个循环会一直执行直到当前节点root为nullptr。

在这个循环中,每次都会将当前节点的值加入向量tre中,然后将当前节点压入栈sta,并将当前节点更新为其左子节点,继续遍历左子树。以此实现先访问根节点,再遍历左子树的前序遍历的一部分。

当内部循环结束时,说明已经遍历到了左子树的最底层,此时从栈中弹出一个节点作为当前节点,并将当前节点更新为其右子节点,继续遍历右子树。如果栈为空且当前节点也为nullptr,说明整个二叉树已经遍历完毕。

完整代码如下:

/**
 * 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> tre;
    stack<TreeNode*> sta;//
    vector<int> preorderTraversal(TreeNode* root) {     
        if (root == nullptr) {
            return tre;
        }
        while (!sta.empty() || root != nullptr) {
            while (root != nullptr) {
                tre.push_back(root->val);
                sta.push(root);
                root = root->left;
            }
            root = sta.top();
            sta.pop();
            root = root->right;
        }
        return tre;
    }
};

时间复杂度为O(n)。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值