代码随想录Day12

二叉树遍历

分为前序、中序、后续、层序四种
其中前中后序属于深度优先搜索,层序属于广度优先搜索

前序遍历顺序:

根节点->左子树->右子树

中序遍历顺序:

左子树->根节点->右子树

后序遍历顺序:

左子树->右子树->根节点
不难发现,前中后其实就是根节点在遍历中的位置
至于层序遍历,顾名思义,就是一层一层的从左到右遍历

递归遍历(前中后)

  1. 确定递归函数的参数和返回值:因为要打印出前序遍历节点的数值,所以参数里需要传入vector来放节点的数值,除了这一点就不需要再处理什么数据了也不需要有返回值,所以递归函数返回类型就是void。
  2. 确定终止条件:在递归的过程中,如何算是递归结束了呢,当然是当前遍历的节点是空了,那么本层递归就要结束了,所以如果当前遍历的这个节点是空,就直接return。
  3. 确定单层递归的逻辑:前序遍历是中左右的顺序,所以在单层递归的逻辑,是要先取中节点的数值。

上代码(●'◡'●)

前序:
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;}
};
中序:
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;}
};
后序:
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;}
};

迭代遍历(前中后)

递归的底层实现其实就是栈
所以我们可以用栈来实现二叉树的前中后序遍历
但是由于会比较麻烦,三种遍历没法统一,所以我们来看另一种方法:
使用栈的话,无法同时解决访问节点(遍历节点)和处理节点(将元素放进结果集)不一致的情况。
那我们就将访问的节点放入栈中,把要处理的节点也放入栈中但是要做标记。
如何标记呢,就是要处理的节点放入栈之后,紧接着放入一个空指针作为标记。 这种方法也可以叫做标记法。
迭代
可以看出我们将访问的节点直接加入到栈中,但如果是处理的节点则后面放入一个空节点, 这样只有空节点弹出的时候,才将下一个节点放进结果集。

上代码(●'◡'●)

前序:
class Solution {
public:vector<int> preorderTraversal(TreeNode* root) {vector<int> result;stack<TreeNode*> st;if (root != NULL) st.push(root);while (!st.empty()) {TreeNode* node = st.top();if (node != NULL) {st.pop();if (node->right) st.push(node->right);  // 右if (node->left) st.push(node->left);    // 左st.push(node);                          // 中st.push(NULL);} else {st.pop();node = st.top();st.pop();result.push_back(node->val);}}return result;}
};
中序:
class Solution {
public:vector<int> inorderTraversal(TreeNode* root) {vector<int> result;stack<TreeNode*> st;if (root != NULL) st.push(root);while (!st.empty()) {TreeNode* node = st.top();if (node != NULL) {st.pop(); // 将该节点弹出,避免重复操作,下面再将右中左节点添加到栈中if (node->right) st.push(node->right);  // 添加右节点(空节点不入栈)st.push(node);                          // 添加中节点st.push(NULL); // 中节点访问过,但是还没有处理,加入空节点做为标记。if (node->left) st.push(node->left);    // 添加左节点(空节点不入栈)} else { // 只有遇到空节点的时候,才将下一个节点放进结果集st.pop();           // 将空节点弹出node = st.top();    // 重新取出栈中元素st.pop();result.push_back(node->val); // 加入到结果集}}return result;}
};
后序:
class Solution {
public:vector<int> postorderTraversal(TreeNode* root) {vector<int> result;stack<TreeNode*> st;if (root != NULL) st.push(root);while (!st.empty()) {TreeNode* node = st.top();if (node != NULL) {st.pop();st.push(node);                          // 中st.push(NULL);if (node->right) st.push(node->right);  // 右if (node->left) st.push(node->left);    // 左} else {st.pop();node = st.top();st.pop();result.push_back(node->val);}}return result;}
};

统一的代码模式,看着确实舒服 d=====( ̄▽ ̄*)b

层序遍历

层序遍历一个二叉树。就是从左到右一层一层的去遍历二叉树。这种遍历的方式和之前的都不太一样。
需要借用一个辅助数据结构即队列来实现,队列先进先出,符合一层一层遍历的逻辑,而用栈先进后出适合模拟深度优先遍历也就是递归的逻辑。
而这种层序遍历方式就是图论中的广度优先遍历,只不过我们应用在二叉树上。
层序遍历

上代码(●'◡'●)

迭代:
class Solution {
public:vector<vector<int>> levelOrder(TreeNode* root) {queue<TreeNode*> que;if (root != NULL) que.push(root);vector<vector<int>> result;while (!que.empty()) {int size = que.size();vector<int> vec;// 这里一定要使用固定大小size,不要使用que.size(),因为que.size是不断变化的for (int i = 0; i < size; i++) {TreeNode* node = que.front();que.pop();vec.push_back(node->val);if (node->left) que.push(node->left);if (node->right) que.push(node->right);}result.push_back(vec);}return result;}
};
递归:
class Solution {
public:void order(TreeNode* cur, vector<vector<int>>& result, int depth){if (cur == nullptr) return;if (result.size() == depth) result.push_back(vector<int>());result[depth].push_back(cur->val);order(cur->left, result, depth + 1);order(cur->right, result, depth + 1);}vector<vector<int>> levelOrder(TreeNode* root) {vector<vector<int>> result;int depth = 0;order(root, result, depth);return result;}
};

写博不易,请大佬点赞支持一下8~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/782919.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

通信组件 --- netlink 原理及应用

什么是netlink netlink是一种基于网络的通信机制,允许内核内部、内核与用户态应用之间甚至用户态应用之间进行通信;netlink的主要作用是内核与用户态之间通信;它的思想是,基于BSD的socket使用网络框架在内核和用户态之间进行通信; 为什么要有netlink 内核中有其他一些方法…

向量数据库和异常数据

书接上文:https://www.cnblogs.com/k4n5ha0/p/18314781 最近学习机器学习期间,了解到了向量数据库:1)可以将文本向量化存储(如上图,将不同语句向量化) 2)在 检索向量的时间复杂 和 对比向量相似度的时间复杂度(例如余弦相似度)充分调优 3)可以调用TPU、GPU等硬件加…

二维差分学习备忘录

二维差分为什么我为OI泪目?因为我菜得离谱......引入 一维差分用来O(1)修改区间,配合上一维前缀和就是O(N)的查询区间和。 差分为前缀和的逆运算。 二维差分同理。 接下来这道题就用二维差分来解决。 \(例题:地毯>>\) 地毯 题目描述 在 \(n\times n\) 的格子上有 \(m\…

4.自定义的信号和槽

自定义信号 1.写到signal下 2.返回void 3.需要声明,不需要实现 4.可以有参数,可以重载 自定义槽函数 1.返回void 2.需要声明,也需要实现 3.可以有参数,可以重载 4.写到pulic slot下或者pulic或者全局函数 触发自定义的信号 1.emit 自定义信号 案例:下课后,老师触发饿了信…

Windows日志致盲与绕过

前言 在渗透测试过程中,Windows日志往往会记录系统上的敏感操作,如添加用户、写计划任务、远程登录执行等操作,对于会审计的安全运维人员或者网络管理员来说,简直就是脱掉衣服走路,被看的一清二楚。对于比较高阶的渗透操作中,要讲究的是动作无感化,来无影去无踪。而对于…

java maven项目配置及IDEA配置

一:maven作用项目管理:编译、测试、打包、部署、运行,这一套流程都可以用maven来管理。管理jar包:也就是上述提到的问题。管理插件:开发过程中会需要使用各种插件。3maven环境变量配置和Java一样,也需要配置maven环境变量。环境变量的作用在于: 可以让该程序在任何路径下…

Go并发原语之SingleFlight

引入 如下图所示,可能存在来自桌面端和移动端的用户有 1000 的并发请求,同一时刻来访问的获取文章列表的接口,获取前 20 条信息,如果这时服务直接去访问 redis 出现 cache miss, 那就会去请求 1000 次数据库,这时可能会给数据库带来较大的压力(这里的1000 只是一个例子,…

词向量的转换理解以及与真实的关系

实际上就是去除该矩阵的某一行。该矩阵实际上就是一个有N个词的300维向量,或者说该矩阵就是一个完整的词向量词汇表。而这个词汇表是通过交叉熵损失最小来构造的。 即归根到底是“在特定语料库中(包含context中共现概率),以数学方法计算输入产生哪些输出”最复合“实际情况…

盘点国内外有哪些软件测试认证

在软件测试行业,技术实力固然重要,但手握权威认证更能为职业发展增添砝码。无论你是刚入行的新人,还是经验丰富的测试工程师,获取一张含金量高的软件测试认证都能让你的职场之路更加平坦。那么,国内外有哪些值得考取的软件测试认证呢?让我们一起来盘点。 你是否正在为选择…

用友金蝶怎么选

财务知识——用友和金蝶选择谁?

概率论沉思录:合情推理

最近蔻享学术主办了每周一次的《概率论沉思录》读书会活动,恰好我也正在读该书中译版,通过该活动我了解到了不同学科的老师(数学/物理/统计/计算机)对这本书的不同理解,而我自己对该书的理解也在这个过程中逐渐深入了。于是准备每周都持续更新一下我的读书笔记。本书作者是…

八重终结 Phase 4 狱火焚天

Ending Time Octet 【八重终结】 Phase 4 Inferno Combusts 【狱火焚天】 PV on Bilibili Part 1 联合动画 Part 1 Part 2 完整音乐 涉及 AU Murder Time Trio Former Time Trio Karmatic Time Trio Chaotic Time Trio Phase 3 Chaotic Time Trio Phase 4 归冢余妄个人曲 传说之…