二叉树—二叉树的前序遍历(leetcode 144)

这篇博客介绍了如何使用迭代算法解决二叉树的前序遍历问题。给定一个二叉树的根节点,算法通过操作空闲指针避免了递归,并在O(n)的时间复杂度和O(1)的空间复杂度下完成遍历。具体实现中,利用两个指针p和q,不断更新它们来遍历每个节点。当遇到没有左子树的节点时,直接访问其值并移动到右子节点;对于有左子树的节点,先将其右指针指向父节点,然后访问其值,最后调整节点的右指针来继续遍历。

题目描述

给你二叉树的根节点 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

进阶:递归算法很简单,你可以通过迭代算法完成吗?

算法分析

https://leetcode-cn.com/problems/binary-tree-preorder-traversal/solution/dong-hua-mo-ni-er-cha-shu-qian-xu-die-da-q9yn/

代码

/**
 * 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) {
        TreeNode* p = root;
        TreeNode* q = nullptr;
        vector<int> ans;
        while(p) {
            q = p->left;
            if(q) {
                while(q->right != nullptr && q->right != p) {
                    q = q->right;
                }
                if(q->right == nullptr) {
                    ans.push_back(p->val);
                    q->right = p;
                    p = p->left;
                    continue;
                } else {
                    q->right = nullptr;
                }
            } else {
                ans.emplace_back(p->val);
            }
            p = p->right;
        }
        return ans;
    }
};

时间复杂度分析

时间复杂度:O(n),其中 n是二叉树的节点数。没有左子树的节点只被访问一次,有左子树的节点被访问两次。

空间复杂度:O(1)。只操作已经存在的指针(树的空闲指针),因此只需要常数的额外空间。

LeetCode 上关于二叉树前序遍历有题目【0144】,以下为相关解答与学习资料: ### 递归方法 递归方法直观,按前序遍历顺序,递归访问每个节点。若当前节点为空则返回;访问当前节点,将节点值添加到结果列表;递归前序遍历左子树和右子树。 ```java import java.util.ArrayList; import java.util.List; class TreeNode { int val; TreeNode left; TreeNode right; TreeNode() {} TreeNode(int x) { val = x; } TreeNode(int x, TreeNode left, TreeNode right) { val = x; this.left = left; this.right = right; } } public class Solution { public List<Integer> preorderTraversal(TreeNode root) { List<Integer> result = new ArrayList<>(); preorder(root, result); return result; } private void preorder(TreeNode node, List<Integer> result) { if (node == null) { return; } result.add(node.val); preorder(node.left, result); preorder(node.right, result); } } ``` 此方法时间复杂度为 $O(N)$,空间复杂度介于 $O(logN)$ 和 $O(N)$ 之间,额外空间复杂度是 $O(1)$ [^5]。 ### 迭代方法 使用栈模拟二叉树前序遍历的递归过程,每次从栈顶弹出节点处理(加入结果集),再将其右子节点和左子节点按顺序压入栈中(先右后左),保证处理顺序符合前序遍历要求(根->左->右),整个过程不使用递归,完全迭代实现。 ```cpp #include <vector> #include <stack> 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: std::vector<int> preorderTraversal(TreeNode* root) { std::stack<TreeNode*> st; std::vector<int> result; if(root==NULL) return result; st.push(root); while(!st.empty()){ TreeNode* node = st.top(); st.pop(); result.push_back(node->val); if (node->right) st.push(node->right); if (node->left) st.push(node->left); } return result; } }; ``` ### C 语言完整代码 ```c #include <stdio.h> #include <stdlib.h> struct TreeNode { int val; struct TreeNode *left; struct TreeNode *right; }; typedef struct TreeNode TreeNode; int TreeSize(TreeNode* root) { if (root == NULL) { return 0; } return 1 + TreeSize(root->left) + TreeSize(root->right); } void preOrder(TreeNode* root, int* arr, int* pi) { if (root == NULL) { return; } arr[(*pi)++] = root->val; preOrder(root->left, arr, pi); preOrder(root->right, arr, pi); } int* preorderTraversal(struct TreeNode* root, int* returnSize) { *returnSize = TreeSize(root); int* tmp = (int*)malloc((*returnSize) * sizeof(int)); if (tmp == NULL) { perror("malloc fail!"); exit(1); } int* arr = tmp; int i = 0; preOrder(root, arr, &i); return arr; } ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值