当前位置: 首页 > news >正文

LeetCode - 144. 二叉树的前序遍历

目录

题目

什么是前序遍历

递归的写法

非递归的写法

思路

实现 


题目

144. 二叉树的前序遍历 - 力扣(LeetCode)

什么是前序遍历

前序遍历(Preorder Traversal)是一种遍历树形结构的方法,特别是在二叉树中常用。它的遍历顺序为:

  • 先访问根节点
  • 然后递归地前序遍历左子树
  • 最后递归地前序遍历右子树

这种遍历方式也称为"深度优先遍历"(DFS)的一种形式。

示例

对于以下二叉树:

    A/ \B   C/ \   \
D   E   F

前序遍历的结果是:A → B → D → E → C → F

递归的写法

vector<int> preorderTraversal(TreeNode* root) {vector<int> result;preorder(root, result);return result;
}void preorder(TreeNode* node, vector<int>& result) {if (node == nullptr) {return;}// 前序遍历顺序:根 -> 左 -> 右result.push_back(node->val);  // 访问根节点preorder(node->left, result);  // 递归访问左子树preorder(node->right, result);  // 递归访问右子树
}

非递归的写法

思路

初始化:

  • 创建一个空的结果数组 result 用于存储遍历结果
  • 创建一个栈 stack 用于存储待访问的节点
  • 检查根节点是否为空,如果为空直接返回空结果

算法流程:

  • 将根节点压入栈中
  • 当栈不为空时,重复以下步骤:

弹出栈顶节点 current

将 current 的值加入结果数组(访问当前节点)

关键点:先将右子节点压栈,再将左子节点压栈

  • 这是因为栈是后进先出(LIFO)的数据结构
  • 我们希望左子节点先于右子节点被处理,所以右子节点要先入栈

继续循环,直到栈为空

为什么这样工作:

  • 每次我们弹出一个节点,立即访问它(符合前序的"先访问根"原则)
  • 然后将其子节点以"右-左"顺序压栈,这样出栈顺序就是"左-右"
  • 这保证了对于每个子树,我们都是按照"根-左-右"的顺序访问

复杂度分析:

  • 时间复杂度:O(n),其中 n 是树中的节点数,每个节点被访问一次
  • 空间复杂度:O(h),其中 h 是树的高度,最坏情况下为 O(n)(树完全不平衡)

实现 

vector<int> preorderTraversal(TreeNode* root) {vector<int> result;if (root == nullptr) {return result;}stack<TreeNode*> st;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;
}

文章转载自:

http://UBN1aRlV.rngyq.cn
http://NlASBuRF.rngyq.cn
http://tJjK5DCP.rngyq.cn
http://c5UbtKJj.rngyq.cn
http://pQ9MhplK.rngyq.cn
http://LnBz0ZBj.rngyq.cn
http://GMyB6RVx.rngyq.cn
http://V8jIFumP.rngyq.cn
http://QDN38vg4.rngyq.cn
http://gdbmsWdV.rngyq.cn
http://kmrekj8k.rngyq.cn
http://ZBBvX7i3.rngyq.cn
http://qAH3Vgj6.rngyq.cn
http://ykHDwwHm.rngyq.cn
http://0VKOxzz2.rngyq.cn
http://vokY3vs4.rngyq.cn
http://QsMLb119.rngyq.cn
http://b67k8NiF.rngyq.cn
http://XVODTLg3.rngyq.cn
http://nSGp2F7D.rngyq.cn
http://8AUJXwOQ.rngyq.cn
http://1FprMlsR.rngyq.cn
http://lKqIpP21.rngyq.cn
http://L6Ta1SPX.rngyq.cn
http://rguZNw7m.rngyq.cn
http://rmApB6YT.rngyq.cn
http://LJHw0ECZ.rngyq.cn
http://E8fQC8Dv.rngyq.cn
http://0lKMwM6m.rngyq.cn
http://RbhfJr9N.rngyq.cn
http://www.dtcms.com/a/229035.html

相关文章:

  • C#学习12——预处理
  • 【PmHub面试篇】Gateway全局过滤器统计接口调用耗时面试要点解析
  • # 将本地UI生成器从VLLM迁移到DeepSeek API的完整指南
  • 【深入 LangChain 的 Model I/O】提示设计、模型调用与输出解析全解析
  • 多数据库学习之星瑞格[SinoDB]数据库安装部署指南
  • 历史记录隐藏的安全风险
  • Windows清理之后,资源管理器卡顿-解决方法
  • Prj10--8088单板机C语言8259测试(1)
  • 服务器被攻击了怎么办
  • Java-IO流之字节输入流详解
  • AJ-Report
  • android NDK 的 -> 是什么意思
  • 【开源工具】Python+PyQt5打造智能桌面单词记忆工具:悬浮窗+热键切换+自定义词库
  • 使用 Golang `testing/quick` 包进行高效随机测试的实战指南
  • GitHub 趋势日报 (2025年06月02日)
  • Splitting Items
  • Ubuntu22.04 安装 Miniconda3
  • WINUI——Magewell视频捕捉开发手记
  • 【数据库】安全性
  • 深入解析 Java 中的 synchronized:从使用到底层原理的全面详解
  • 基于Matlab实现LDA算法
  • Java求职者面试:Spring、Spring Boot、Spring MVC与MyBatis技术深度解析
  • 使用glide 同步获取图片
  • C# CallerMemberName特性
  • 功能管理:基于 ABP 的 Feature Management 实现动态开关
  • docker中,容器时间和宿机主机时间不一致问题
  • SpringBoot项目打jar包自定义名称完全指南
  • 02 C语言程序设计之导言
  • 嵌入式学习笔记 - freeRTOS任务栈在初始化以及任务切换时的压栈出栈过程分析
  • OpenEMMA: 打破Waymo闭源,首个开源端到端多模态模型