给「代码随想录」一个星标吧!

以后每周加上一个本周小结怎么样?

本周小结

发现大家周末的时候貌似都不在学习状态,周末的文章浏览量和打卡情况照工作日差很多呀,可能是本周日是工作日了,周六得好好放松放松,哈哈,理解理解,但我还不能不更啊,还有同学要看呢。

所以呢,「周日我做一个针对本周的打卡留言疑问以及在刷题群里的讨论内容做一下梳理吧。」,这样也有助于大家补一补本周的内容,消化消化。

「注意这个周末总结和系列总结还是不一样的(二叉树还远没有结束),这个总结是针对留言疑问以及刷题群里讨论内容的归纳。」

周一

本周我们开始讲解了二叉树,在关于二叉树,你该了解这些!中讲解了二叉树的理论基础。

有同学会把红黑树和二叉平衡搜索树弄分开了,其实红黑树就是一种二叉平衡搜索树,这两个树不是独立的,所以C++中map、multimap、set、multiset的底层实现机制是二叉平衡搜索树,再具体一点是红黑树。

对于二叉树节点的定义,C++代码如下:

struct TreeNode {    int val;    TreeNode *left;    TreeNode *right;    TreeNode(int x) : val(x), left(NULL), right(NULL) {}};

对于这个定义中TreeNode(int x) : val(x), left(NULL), right(NULL) {} 有同学不清楚干什么的。

这是构造函数,这么说吧C语言中的结构体是C++中类的祖先,所以C++结构体也可以有构造函数。

构造函数也可以不写,但是new一个新的节点的时候就比较麻烦。

例如有构造函数,定义初始值为9的节点:

TreeNode* a = new TreeNode(9);

没有构造函数的话就要这么写:

TreeNode* a = new TreeNode(); a->val = 9; a->left = NULL;a->right = NULL;  

在介绍前中后序遍历的时候,有递归和迭代(非递归),还有一种牛逼的遍历方式:morris遍历。

morris遍历是二叉树遍历算法的超强进阶算法,morris遍历可以将非递归遍历中的空间复杂度降为O(1),感兴趣大家就去查一查学习学习,比较小众,面试几乎不会考。我其实也没有研究过,就不做过多介绍了。

周二

在二叉树:一入递归深似海,从此offer是路人中讲到了递归三要素,以及前中后序的递归写法。

文章中我给出了leetcode上三道二叉树的前中后序题目,但是看完二叉树:一入递归深似海,从此offer是路人,依然可以解决n叉树的前后序遍历,在leetcode上分别是

  • 589 . N叉树的前序遍历
  • 590 . N叉树的后序遍历

大家可以再去把这两道题目做了。

周三

在二叉树:听说递归能做的,栈也能做!中我们开始用栈来实现递归的写法,也就是所谓的迭代法。

细心的同学发现文中前后序遍历空节点是入栈的,其实空节点入不入栈都差不多,但感觉空节点不入栈确实清晰一些,符合文中动画的演示。

前序遍历空节点不入栈的代码:(注意注释部分,和文章中的区别)

class Solution {public:    vector preorderTraversal(TreeNode* root) {        stack st;        vector 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;    }};

后序遍历空节点不入栈的代码:(注意注释部分,和文章中的区别)

class Solution {public:    vector postorderTraversal(TreeNode* root) {        stack st;        vector 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->left) st.push(node->left); // 相对于前序遍历,这更改一下入栈顺序 (空节点不入栈)if (node->right) st.push(node->right); // 空节点不入栈        }        reverse(result.begin(), result.end()); // 将结果反转之后就是左右中的顺序了return result;    }};

在实现迭代法的过程中,有同学问了:递归与迭代究竟谁优谁劣呢?

从时间复杂度上其实迭代法和递归法差不多(在不考虑函数调用开销和函数调用产生的堆栈开销),但是空间复杂度上,递归开销会大一些,因为递归需要系统堆栈存参数返回值等等。

递归更容易让程序员理解,但收敛不好,容易栈溢出。

这么说吧,递归是方便了程序员,难为了机器(各种保存参数,各种进栈出栈)。

「在实际项目开发的过程中我们是要尽量避免递归!因为项目代码参数、调用关系都比较复杂,不容易控制递归深度,甚至会栈溢出。」

周四

在二叉树:前中后序迭代方式的写法就不能统一一下么?中我们使用空节点作为标记,给出了统一的前中后序迭代法。

此时又多了一种前中后序的迭代写法,那么有同学问了:前中后序迭代法是不是一定要统一来写,这样才算是规范。

其实没必要,还是自己感觉哪一种更好记就用哪种。

但是「一定要掌握前中后序一种迭代的写法,并不因为某种场景的题目一定要用迭代,而是现场面试的时候,面试官看你顺畅的写出了递归,一般会进一步考察能不能写出相应的迭代。」

周五

在二叉树:层序遍历登场!中我们介绍了二叉树的另一种遍历方式(图论中广度优先搜索在二叉树上的应用)即:层序遍历。

看完这篇文章,去leetcode上怒刷五题,文章中 编号107题目的样例图放错了(原谅我匆忙之间总是手抖),但不影响大家理解。

只有同学发现leetcode上“515. 在每个树行中找最大值”,也是层序遍历的应用,依然可以分分钟解决,所以就是一鼓作气解决六道了,哈哈。

「层序遍历遍历相对容易一些,只要掌握基本写法(也就是框架模板),剩下的就是在二叉树每一行遍历的时候做做逻辑修改。」

周六

在二叉树:你真的会翻转二叉树么?中我们把翻转二叉树这么一道简单又经典的问题,充分的剖析了一波,相信就算做过这道题目的同学,看完本篇之后依然有所收获!

「文中我指的是递归的中序遍历是不行的,因为使用递归的中序遍历,某些节点的左右孩子会翻转两次。」

如果非要使用递归的中序的方式写,也可以,如下代码就可以避免节点左右孩子翻转两次的情况:

class Solution {public:    TreeNode* invertTree(TreeNode* root) {        if (root == NULL) return root;        invertTree(root->left);         // 左        swap(root->left, root->right);  // 中        invertTree(root->left);         // 注意 这里依然要遍历左孩子,因为中间节点已经翻转了        return root;    }};

代码虽然可以,但这毕竟不是真正的递归中序遍历了。

但使用迭代方式统一写法的中序是可以的。

代码如下:

class Solution {public:    TreeNode* invertTree(TreeNode* root) {        stack 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();                swap(node->left, node->right);          // 节点处理逻辑            }        }return root;    }};

为什么这个中序就是可以的呢,因为这是用栈来遍历,而不是靠指针来遍历,避免了递归法中翻转了两次的情况,大家可以画图理解一下,这里有点意思的。

总结

「本周我们都是讲解了二叉树,从理论基础到遍历方式,从递归到迭代,从深度遍历到广度遍历,最后再用了一个翻转二叉树的题目把我们之前讲过的遍历方式都串了起来。」

下周依然是二叉树,大家加油!

在留言区留下你的思路吧!

-------end-------

我将算法学习相关的资料已经整理到了Github :https://github.com/youngyangyang04/leetcode-master,里面还有leetcode刷题攻略、各个类型经典题目刷题顺序、思维导图看一看一定会有所收获,如果给你有帮助给一个star支持一下吧!

另外因为公众号改版,时间线被打乱,一些精彩文章大家可能错过了。如果感觉这里的文章对你有帮助,赶紧给「代码随想录」加一个星标吧,方便第一时间阅读文章往期精彩回顾二叉树:你真的会翻转二叉树么?二叉树:层序遍历登场!二叉树:前中后序迭代方式的写法就不能统一一下么?二叉树:听说递归能做的,栈也能做!二叉树:一入递归深似海,从此offer是路人关于二叉树,你该了解这些!「代码随想录」期待你的关注!

每天8:35准时推送一道经典算法题目,推送的每道题目都不是孤立的,而是由浅入深,环环相扣,帮你梳理算法知识脉络,轻松学算法!

刷题可以加我微信!右边为个人微信,添加时备注:「简单自我介绍」+「组队刷题」我就知道你[在看]

6-4 二叉树的非递归遍历 (25分)_本周小结!(二叉树)相关推荐

  1. 6-9 二叉树的非递归遍历 (20 分)

    ** 6-9 二叉树的非递归遍历 (20 分) ** 本题要求用非递归的方法实现对给定二叉树的 3 种遍历. 函数接口定义: void InorderTraversal( BinTree BT ); ...

  2. 创建的二叉树后续非递归遍历结果为_一入递归深似海,从此offer是路人

    前言 今天我们来总结二叉树的前中后序以及层次遍历的递归与非递归的写法.我们都知道二叉树遍历的递归写法很简单,但是面试的时候面试官往往考察的不是我们递归的写法,他们满怀期待你写出非递归的解法,而当你只会 ...

  3. 刷题:二叉树的非递归遍历方式

    二叉树的非递归的遍历方式 上篇博客记录了二叉树的递归遍历方式以及根据二叉树的遍历结果还原二叉树的内容. 本篇博客记录二叉树的非递归的遍历方式. 二叉树的非递归遍历需要借助栈来实现,而且三种遍历的方式的 ...

  4. 二叉树的非递归遍历(c/c++)

    由于递归算法相对于非递归算法来说效率通常都会更低,递归算法会有更多的资源需要压栈和出栈操作(不仅仅是参数,还有函数地址等)由于编译器对附加的一些栈保护机制会导致递归执行的更加低效,使用循环代替递归算法 ...

  5. 二叉树的非递归遍历(统一的模板)

    二叉树的非递归遍历 前言 树的存储结构 先序遍历 先序的递归遍历 先序的非递归遍历 中序遍历 中序的递归遍历 中序遍历的非递归算法 后序遍历 后序的递归遍历 后序的非递归遍历 层次遍历 层次遍历获得每 ...

  6. 数据结构-二叉树的非递归遍历

    前面的章节我们实现了二叉树最基本的遍历方式:递归遍历,代码是如此的简洁:辣么我们为什么还要去学习二叉树的非递归遍历方式呢?众所周知,递归优点是将可以将复杂的问题简单化即大问题拆分成一个个小问题,那么它 ...

  7. c语言以顺序结构存储的二叉树的非递归遍历,C语言二叉树的非递归遍历实例分析...

    本文以实例形式讲述了C语言实现二叉树的非递归遍历方法.是数据结构与算法设计中常用的技巧.分享给大家供大家参考.具体方法如下: 先序遍历: void preOrder(Node *p) //非递归 { ...

  8. 树:二叉树的非递归遍历算法

    二叉树的递归遍历 二叉树的递归遍历算法,写法很简单,比如说前序遍历树,如下: //前序遍历 void PreOrderTraverse(BiTree tree) {if (NULL != tree){ ...

  9. C/C++ 二叉树的非递归遍历(前序、中序、后序非递归遍历)

     二叉树的非递归遍历C/C++实现:   非递归先序遍历代码: void PreOrderTraversal (struct tree* root) { //非递归先序遍历struct tree* t ...

最新文章

  1. java 计划日视图,GitHub - sddysz/calendarSchedule: 日程表,仿滴答清单,包含日视图、三日视图、周视图、月视图、列表视图、同步手机系统日程、添加日程...
  2. NOI2018 Day1 归程(return)
  3. java 三种将list转换为map的方法详解
  4. CAN词典 - CANdictionary
  5. WebKit DOM Event (二)
  6. Netty私有栈协议
  7. 推荐算法-关联分析(关联规则)
  8. linux内核rest_init分析
  9. sqlplus / as sysdba 提示权限不足(ORA-01031)问题处理
  10. AMD宣布350亿美元收购赛灵思,CPU、GPU、FPGA全凑齐
  11. ubuntu 18.04使用sysbench测试MySQL性能
  12. java自动化执行javascript,Js代码执行__实现自动化
  13. python求解非线性多元方程_求解python中的colebrook(非线性)方程
  14. Android Studio下载
  15. 这个城市快递外卖小哥将配电子号牌了,违法2起以上停止派单
  16. c++ 结构体中不同类型的初始值_不同类型结构的厂房效果图大盘点
  17. Python 实例教程
  18. 决策支持系统是什么?
  19. ghostscript的坑
  20. VMware Workstation中的虚拟共享存储

热门文章

  1. python能做机器人吗_python深度学习 人工智能是做机器人吗?
  2. 机器学习:sklearn数据集与机器学习组成
  3. R语言第六讲 数据的统计分析
  4. java封装省市区三级json格式,微信开发 使用picker封装省市区三级联动模板
  5. Hive关于数据表的增删改(内部表、外部表、分区表、分桶表 数据类型、分隔符类型)
  6. ACL20 Best Paper揭晓!NLP模型评价体系或将迎来重大转折
  7. 美团深度学习系统的工程实践
  8. 2018最新Java面试78题:数据结构+网络+NoSQL+分布式架构
  9. 阿里java架构师面试128题含答案:分布式架构+Dubbo+多线程+Redis
  10. 领域应用 | 小米在知识表示学习的探索与实践