首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

数据结构+算法(第13篇):精通二叉树“独门忍术”——线索二叉树(上)

“前序遍历”规则: 先访问当前节点,再访问其子树,最后访问右子树; 访问子树时,按照规则1递归执行。...“序遍历”规则: 先访问子树,再访问当前节点,最后访问右子树; 访问子树时,按照规则1递归执行。...“后序遍历”规则: 先访问子树、再访问右子树,最后访问当前节点; 访问子树时,按照规则1递归执行。 如果要写出非递归遍历算法,无论用哪种遍历方法,根据《再不会“降维打击”你就Out了!》...“序遍历”线索二叉树说白了,就是两条规则: 将当前节点子树最右叶子节点右孩子指针指向当前节点本身; 对每个节点,递归执行规则1。 规则1看起来比较绕,用一张来表示: ?...2 “序遍历”线索二叉树 2就是1对应序遍历”线索二叉树。 线索二叉树意义 传统递归型遍历算法,最挑战地方在于要记忆“回溯点”。

86720

【数据结构】二叉树(遍历,递归

今日更新了树遍历,递归相关内容 欢迎大家关注点赞收藏⭐️留言 二叉树遍历规则 ​ 前序遍历 ​ 注意:N代表空 分析:根据前序遍历规则(根左右),先访问根1,然后子树2,2子树3...序遍历 分析:根据规则根右),1子树2,2子树3,3子树N,起始即为N,接着是根3,接着是3右子树N,返回到根2,然后是2右子树N,返回到根1,接着是1右子树,以此类推。...下图是递归流程: 分析:开始先打印根1,然后递归调用根2,以此类推到3子树N。此时子树遍历完,返回到3右子树,每次调用完就返回到上一层函数。...序 上图是序遍历函数,递归过程参考前序遍历过程。 后序遍历大致过程也同上,这里就不再写出。 求节点个数 递归过程如下: 分析:如果根结点为空,则返回0。...递归过程会先找出子树节点个数,当遇到空节点时就返回0,然后加上根结点自身数量1,返回到上一层,以此类推。 求叶子节点个数 参考前面的递归过程理解。

9910
您找到你想要的搜索结果了吗?
是的
没有找到

leetcode 22 括号生成 js 实现

: * - 必须是有效组合,则、右括号一定要小于n, 且右括号数量要一直小于或等于左括号 * - 针对组成括号字符串每一个位置字符来说,要么是括号,要么是右括号, 具体这个位置应该是还是右...,看上面的规则而定 * - 所以想到,我可以递归地往每个位置放和右括号,如果违反了规则,就回溯回去,换一个放,由此想到了回溯算法 * - 既然是递归,首先要先想好终止条件,依题可知,如果左右括号数量都为...n的话,即为一个答案了,终止递归,返回即可 * 解题:left 记录已经放入括号数量; right 记录右括号数量;str 表示当前组成字符串 */ // https://leetcode.cn...,可以添加一个括号,但是括号总数不增加 // 当右括号数量小于左括号时,可以添加一个右括号,括号总数加1 // 当括号总数等于n时,返回当前缓存数组值 var generateParenthesis...结束递归,进入下一行 console.log("left temp",temp) dfs(index, left+1, right, temp);

1.5K20

TypeScript实现二叉搜索树

方法,传当前节点子节点和回函数 调用函数 递归调用inOrderTraverseNode方法,传当前节点右子节点和回函数 接下来,我们通过一个例子来描述下序遍历过程 如上图所示,蓝色字标明了节点访问顺序...,橙色线条表示递归调用直至节点为null然后执行回函数。...preOrderTraverseNode方法接收参数与序遍历一样 递归基线条件: node == null 调用函数 递归调用preOrderTraverseNode方法,传当前节点子节点和回函数...方法,接收参数与序遍历一致 递归基线条件为node == null 递归调用postOrderTraverseNode方法,传当前节点子节点和回函数 递归调用postOrderTraverseNode...如上图所示,蓝色字标示了节点执行顺序,橙色线表示递归调用直至节点为null然后执行回函数。

47220

消除文法递归

简介 1.直接递归消除 消除产生式直接递归是比较容易。例如假设非终结符P规则为 P→Pα / β 其中,β是不以P开头符号串。...全部规则; 消除Ai规则直接递归; } 化简由(2)所得到文法,即去掉多余规则。...利用算法可以将上述文法进行改写,来消除递归。 首先,令非终结符排序为R、Q、S。对于R,不存在直接递归。把R代入到Q相关规则,则Q规则变为Q→Sab/ ab/ b。...接着,要解决间接递归问题,因此将间接递归转换成直接递归。最后将消除直接递归。...第二个问题,消除递归文法后有一部分非终结符及其产生式无用,因此需要将其去处,使用DFS从开始符S开始检测非终结符,最终可以解决此种问题

3.9K30

看懂编译原理:词法语法语义分析阶段 原理

耗时长且优化效果很差因此将ast优化放置在了分析阶段最后一个阶段:语义分析语法分析阶段:递归问题递归问题定义递归问题:匹配加法文法时 由于第二个文法(add+mutil)第一个条件也是加法文法...如此一直往复循环匹配是读取一定数量token去匹配各种规则而不是单独一个token就直接去匹配递归问题 分析& 解决方案解决:原因是第二条文法规则里面第一个条件和主文法第一个条件 重复了就会递归调用...ps:递归问题同样如果采用右边先遍历也会出现右递归问题。...深度上会出现递归,横向上节点生成则是拍平后递归递归问题总结递归问题:匹配加法文法时由于子规则第二个条件也是加法文法因此只要第一个文法条件不满足,匹配第二条文法节点时又会递归判断是否是加法文法,第二次也如次...(也叫回溯)注意:文法结构只表达对应构成规则,对于如何用算法实现文法结构规则是算法事情(如出现递归 说明文法节点结构第一个条件就是再次判断是否符合该文法父节点,如此循环。)

68220

数据结构之树-第二篇

在将递归调用, 是将新元素e作为node子节点插入进去。...递归过程,就要从这个二分搜索树根节点开始,逐渐转移在新二分搜索树子树, 242 // 缩小问题规模,缩小查询规模,直到发现找到这个元素e或者找不到这个元素e。...// 如果待查询元素e小于node元素e,如果二分搜索树还包含元素e的话,那么只可能在node子树 271 return contains(node.left, e);...// 递归调用根节点root子树。...但是如果想要在一棵树中找到某个问题解的话, 452 * 对于深度优先遍历来说,将从根节点一下子访问到树最深地方, 453 * 但是问题解很可能在树上面,所以深度优先遍历先估计子树

42310

【算法】快速排序算法编码和优化

原数组被划分为2份 通过递归处理, 再对原数组分割两部分分别划分为两部分,同样是使得其中一部分所有数据都小于另一部分所有数据。...图中步骤3,4不难理解,这里就不多赘述,因为步骤3递归思想是大家比较熟悉, 步骤4“组合”其实就只是个概念上词,因为所有的子数组本来就连接在一起,只要所有的递归结束了,整个数组就是有序。...那么就我们就会发现一个问题: 当游标向右扫描时候,第一个遇到“大于或等于”元素就是它本身, 那么问题来了: 需不需要停下来呢?...【注意】这里你可能会问: 在我们制定规则里, 游标先扫描和右游标先扫描有区别吗?...回忆一下我在前面提到快排对左右游标指定规则游标向右扫描, 跨过所有小于基准元素数组元素, 直到遇到一个大于或等于基准元素数组元素, 在那个位置停下。

1.6K120

数据结构+算法(第14篇):精通二叉树“独门忍术”——线索二叉树(

我们先来对比一下“序遍历”线索二叉树与“前序遍历”线索二叉树图示: ? 1 “序遍历”线索二叉树 ?...2 “前序遍历”线索二叉树 对比2与1可以看出: “序遍历”线索二叉树与“前序遍历”线索二叉树区别仅仅在于后继节点位置——前者是当前节点,后者是当前节点直接右孩子。...我们来看看是否可以利用传统线索二叉树——即“序遍历”线索二叉树,来实现这一目标:非递归地、不用堆栈来做“前序遍历”。 前序遍历规则简单归纳就是:递归执行“根”->“”->“右”。...下面的几张图表示了从树根开始“前序遍历”一部分子树过程。其中current指针表示当前位置,蓝色闪电表示该位置进行遍历输出,橙黄色箭头表示current指针移动方向。 ?...先将当前节点前驱节点找到,链接起来便形成“序遍历”线索二叉树;同时,当前节点是当前局部线索二叉树树根,根据“根”->“”->“右”前序遍历规则,应该输出当前位置作为“根”信息。 ?

41520

数据结构与算法:链式二叉树

3右子树 3函数结束,返回到上一层函数,来对2右子树进行访问,以此类推 递归展开可以更好帮我们理解递归过程 有了上述讲解,序遍历和后续遍历则变得很简单了 序遍历代码: void...递归分解问题递归地计算子树节点个数和右子树节点个数。 合并结果:将子树节点数和右子树节点数相加,然后加1(代表当前节点),得到总和就是整个二叉树节点个数。...识别叶子节点:如果当前节点既没有子树也没有右子树,意味着它是一个叶子节点,因此返回1。 递归分解问题:如果当前节点不是叶子节点,递归地计算子树叶子节点个数和右子树叶子节点个数。...递归调用DestroyTree(root->left);销毁子树。这将遍历到最左侧叶子节点,沿途经过每个节点子树都将被先递归调用DestroyTree处理。...第二部分:检查队列剩余所有节点是否都是空 退出第一部分循环后,理论上队列剩下所有节点应该都是空节点(如果是完全二叉树的话)。

8110

数据结构之树(Topk问题, 链式二叉树)

1.概念及应用场景 双路递归是一种算法思想,指的是在递归过程同时处理两个子问题,从而提高递归效率和性能。...在处理一些问题时,双路递归比单路递归更有效率,例如在归并排序,双路递归可以同时对半部分和右半部分进行排序,然后将它们合并成一个有序序列,从而减少了排序时间复杂度。...另外,在一些搜索问题中,双路递归也可以更快地找到目标元素,例如在二叉搜索树,可以同时从子树和右子树进行搜索,从而更快地找到目标元素。...- 双路递归优点: - 可以减少重复计算,提高效率。 - 可以处理一些复杂问题,如二叉树遍历、深度优先搜索等。...双路递归空间复用是指在递归过程重复利用之前开辟空间,以减少内存使用量。以 longlong Fib(size_t N) 函数为例,该函数用是计算斐波那契数列第 N 个数值。

9710

二叉树各种遍历真的很难?大sai带你拿捏!

结束边界:节点(或右)子节点为null那么就停止对应节点递归执行。 正常点逻辑:先处理当前点(存储或输出),递归调用枚举子树(如果不为null),递归调用枚举右子树(如果不为null)。...非递归前序还是非常简单,前序遍历规则是:根节点,节点,右节点。...二叉树序遍历出现频率还是蛮高,如果是二叉排序树相关问题还是蛮多,你要知道二叉排序树序遍历是一个有序序列,如果求二叉排序树topk问题,非递归中序那效率是非常高。...非递归序和前序是非常相似的,前序遍历规则是:根节点,节点,右节点。...一些操作可以借助这张进行理解: 具体实现上,可以使用一个HashMap存储序存储序列,避免重复计算。

60930

数据结构与算法(五)| 递归行为及其时间复杂度分析

从思想上理解递归 递归行为从大问题划分为同等结构问题着手,每个小问题都和上一级问题是同等结构,同等结构问题解决了之后所收集来信息通过分析能够整合出大问题返回值。...:[L..Mid] 右:[Mid+1..R] 2)部分求最大值,右部分求最大值 3) [L..R]范围上最大值,是max{部分最大值,右部分最大值} 注意:部分求最大值,右部分求最大值 是个递归过程...递归函数调用图解 针对上述递归函数,后续我们可以这么画图模拟调用: ? 递归过程 这就是递归调用逻辑。把调用过程画出结构图是必须,这有利于分析递归。...通过一个简单例题分析得知,递归底层是利用系统栈来实现。平时分析递归时候,建议画出逻辑来辅助分析递归行为。 4....: 所以有: 该递归函数整体上还有一部分时间是计算 「leftMax」 和 「rightMax」 最大值,这部分时间复杂度为O(1),所以,该递归函数时间复杂度就是: 所以代入到时间复杂度公式

79130

CART算法学习及代码实现

剪枝:在CART过程第二个关键思想是用独立验证数据集对训练集生长树进行剪枝。 分析分类回归树递归建树过程,不难发现它实质上存在着一个数据过度拟合问题。...因此试图检测和减去这样分支,检测和减去这些分支过程被称为树剪枝。树剪枝方法用于处理过分适应数据问题。...(thisNode);函数用是将thisNode样本尝试进行最优划分,划分依据就是杂质最大该变量,如果划分成功返回属性下标,否则返回-1,我们在样本每个属性默认取两个离散值。...nodenum第一个作用是遍历,将每一个节点赋予一个唯一值,建树过程是前序建树,建树结束后根据树序遍历可以唯一确定树结构,nodenum第二个作用和leavenode作用将会在剪枝过程中用到...当建树结束后,树前序即为nodenum从小到大排序,然后通过调用序遍历函数输出树序序列,确定树结构。该树含有17个决策点(非叶子节点),18个叶子节点。 ? ? 1.

1.9K40

Android技能树 — 树基础知识小结(一)

单单看这个,其实换成我,我也看不懂规律,但是我们只需要懂得其中规则就行。...print(t) //第二步,递归方式继续调用该方法遍历孩子 遍历(t.孩子) //第三步,递归方式继续调用该方法遍历右孩子 遍历(t...伪代码: 遍历(结点对象 t){ if( t == null){ return; } //第一步,递归方式继续调用该方法遍历孩子...print(t) //第三步,递归方式继续调用该方法遍历右孩子 遍历(t.右孩子) } 复制代码 我们发现只要把我们打印语句放在中间,就是序遍历了。...但是这时候又有一个问题,就是我们不知道这个点目前到底放是前驱还是子结点指针,所以我们还需要一个参数来说明当前这个位置放是哪个指针。 ?

40730

终于弄懂算法递归执行过程

递归实现原理: 一个递归函数调用过程类似于多个函数嵌套调用,只不过调用函数和被调用函数是同一个函数。为了保证递归函数正确执行,系统需设立一个工作栈。...以上代码例子计算sum(n=3)出入栈如下: 为了更容易理解一些,我们来看一下 函数sum(n=5)递归执行过程,如下: 计算sum(5)时,先sum(5)入栈,然后原问题sum(5)拆分为子问题...我们就用n等于5时候来画个看一下递归究竟是怎么调用: 这种递归还是很简单,我们求f(5)时候,只需要求出f(4)即可,如果求f(4)我们要求出f(3)……,一层一层调用,当n=1时候,我们直接返回...递归目的是把一个大问题细分为更小问题,我们只需要知道递归函数功能即可,不要把递归一层一层拆开来想,如果同时调用多次的话这样你很可能会陷入循环而出不来。...前序遍历: 终止条件是node等于空,逻辑处理这块直接打印当前节点值即可,递归调用是先打印子树在打印右子树,我们来看下 public static void preOrder(TreeNode node

3.2K21

遍历二叉树—前序遍历算法VBA代码解析

遍历二叉树》,我们给出了遍历二叉树三种方式:前序遍历、序遍历、后序遍历,以及对应规则和示意图。下面,我们给出实现这三种遍历算法VBA代码并详细解析代码运行过程。...5 5.再次执行语句PreOrder btTree.Node(i).LeftChild,访问结点H子树,此时其结点值为空,过程返回;接着调用PreOrder btTree.Node(i).RightChild...该层递归调用过程执行完毕,返回到上一级递归调用过程,即调用结点D过程。...也返回到上一级递归过程,即打印节点B过程,递归调用执行PreOrder btTree.Node(i).RightChild语句,访问结点B右子树,打印结点数据E,如下图7所示。 ? 7 7....9 9.类似前面的递归调用,依次继续打印结点F、G。 综上,前序遍历这棵二叉树结点顺序是:ABDHIEJCFG。 本文所讲解前序遍历原理也可以参考《大话数据结构》P178-P181。

72040

Python 之父解析器系列之五:递归 PEG 语法

我曾几次提及递归是一块绊脚石,是时候去解决它了。基本问题在于:使用递归下降解析器时,递归会因堆栈溢出而导致程序终止。 【这是我 PEG 系列第 5 部分。...(pgen 与递归规则具有同样问题)。...我看到它适用于玩具语法 expr 等简单情况,也适用于更复杂情况(例如,涉及一个备选项里可选条目背后藏着递归,或涉及多个规则之间相互递归),但在 Python 语法,我能想到最复杂情况仍然相当温和...所以让我们坚持干,并展示一些真实代码。 首先,解析器生成器必须检测哪些规则递归。这是图论中一个已解决问题。...我不会在这里展示算法,事实上我将进一步简化工作,并假设语法唯一递归规则就是直接递归,就像我们玩具语法 expr 一样。然后检查递归只需要查找以当前规则名称开头备选项。

81530

数据结构与算法入门手册

图片 第一部分:算法概述 算法定义:一系列解决问题清晰易行步骤和规则。以编程实现,输入为问题实例,输出为问题解。 算法特征:输入、输出、有穷性、确定性、可行性。...二叉树:递归与迭代方式实现前序、序与后序遍历,层次遍历队列实现。 5.搜索:BFS与DFS实现与应用场景对比,最短路径算法如Dijkstra算法与Floyd算法。...需合并子问题解为原问题解,通常更高效。 二分查找:在有序数组查找目标值,每次比较中间元素,递归区间或右区间。...快速排序:从数组中选取一个pivot,小于pivot放区间,大于pivot放右区间,递归区间和右区间。 动态规划:通过拆分为子问题并保存子问题解避免重复计算,典型例子背包问题、最长公共子序列。...递归调用 O(nlogn) 不稳定 归并排序:递归地拆分序列,合并有序子序列 O(nlogn) 稳定 最短路径:寻找图中两个节点之间最短路径长度。Dijkstra算法与Floyd算法。

54340
领券