热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

二叉树的遍历问题

目录一、二叉树1、二叉树结点结构2、递归遍历3、非递归遍历①非递归先序遍历②非递归中序遍历③非递归后序遍历4、二叉树的宽度优先遍历①宽度优先遍历一、二叉树1、二叉

目录

一、二叉树

1、二叉树结点结构

2、递归遍历

3、非递归遍历

①非递归先序遍历

②非递归中序遍历

③非递归后序遍历

4、二叉树的宽度优先遍历

①宽度优先遍历




一、二叉树


1、二叉树结点结构

struct BinaryNode
{int val;BinaryNode* left;BinaryNode* right;
}

2、递归遍历

①先序遍历:对每一棵树和子树都是先遍历头结点,然后再是左结点,最后是右结点。

②中序遍历:对每一棵树和子树都是先遍历左结点,然后再是头结点,最后是右结点。

③后序遍历:对每一棵树和子树都是先遍历左结点,然后再是右结点,最后是头结点。

void recursion(struct BinaryNode * root)
{if (root == NULL){return;}//先序遍历printf("%d ", root->val);recursion(root->lChild);recursion(root->rChild);
}void recursion(struct BinaryNode * root)
{if (root == NULL){return;}recursion(root->lChild);//中序遍历printf("%d ", root->val);recursion(root->rChild);
}void recursion(struct BinaryNode * root)
{if (root == NULL){return;}recursion(root->lChild);recursion(root->rChild);//后序遍历printf("%d ", root->val);
}

 总结:第一次来到结点的时候打印就是先序遍历、第二次来到结点打印就是中序遍历、第三次来到结点打印就是后续遍历


3、非递归遍历

二叉树的非递归遍历需要用到栈容器,下面会对非递归遍历进行详细介绍


①非递归先序遍历


步骤:

(1) 先压入头节点

(2) 从栈中弹出一个结点cur

(3) 打印cur

(4) 先压右结点,再压左结点(如果有)

(5) 重复 (2) --- (4) 直到栈为空


代码如下:

//先序非递归
void prenorecursion(BinaryNode* headnode)
{printf("先序遍历:");if (headnode){stack s;s.push(headnode);while (s.size()){//1、弹出栈顶元素headnode = s.top();s.pop();//2、打印printf("%d ", headnode->m_Val);//3、如果有左右结点,先压入右结点,再压入左结点if (headnode->m_RightNode){s.push(headnode->m_RightNode);}if (headnode->m_LeftNode){s.push(headnode->m_LeftNode);}}}
}

②非递归中序遍历

中序非递归遍历的思想就是先把左边的结点全部压入到栈,直到为空,然后开始弹出结点并打印,弹出的时候将右边的结点也压入栈,重复上述步骤。

代码如下:

//中序非递归
void midnorecursion(BinaryNode* headnode)
{printf("中序遍历:");if (headnode){stack s;while (s.size() || headnode){//只要左结点不为空,一直压入栈中if (headnode){s.push(headnode);headnode = headnode->m_LeftNode;}//左边压完了,弹出结点的同时检查右边是否有结点,如果有,将右边结点压入并重复检测有无左结点else{headnode = s.top();printf("%d ", headnode->m_Val);s.pop();headnode = headnode->m_RightNode;}}}
}

③非递归后序遍历


步骤:

(1) 先压入头结点

(2) 弹出cur,将cur压入收集栈

(3) 先压左结点,再压右结点(如果有)

(4) 重复(2) --- (4) 直到栈为空

(5) 依次弹出收集栈元素并打印


 代码如下:

//后序非递归
void afternorecursion(BinaryNode* headnode)
{printf("后序遍历:");if (headnode){stack s;//容器栈stack collectstack;//收集栈//1、压入头结点s.push(headnode);while (s.size()){//2、弹出栈顶元素,并压入收集栈headnode = s.top();s.pop();collectstack.push(headnode);//3、将栈顶元素的左结点、右节点压入栈中(如果有的话)if (headnode->m_LeftNode){s.push(headnode->m_LeftNode);}if (headnode->m_RightNode){s.push(headnode->m_RightNode);}}//4、当栈中元素为空,依次弹出收集栈中元素并打印while (collectstack.size()){headnode = collectstack.top();printf("%d ", headnode->m_Val);collectstack.pop();}}
}

4、二叉树的宽度优先遍历

如何完成二叉树的宽度优先遍历(常见题目:求一颗二叉树的宽度)


①宽度优先遍历

宽度优先遍历上图中就是 1->2->3->4->5->6->7->8->9

算法思想: 使用一个队列(可以是数组或链表)来完成。初始时只有一个根节点,然后每次取出一个结点,就把它的左右儿子(如果有)放入队列。

代码如下:

void treewidth(BinaryNode* headnode)
{queue q;//1、先放头节点q.push(headnode);while (q.size()){//2、弹出结点并打印headnode = q.front();printf("%d ", headnode->m_Val);q.pop();//3、放入左结点和右节点(如果有)if (headnode->m_LeftNode){q.push(headnode->m_LeftNode);}if (headnode->m_RightNode){q.push(headnode->m_RightNode);}}
}


推荐阅读
  • 题目链接:POJ 2777。问题描述:给定一个区域,需要进行多次涂色操作,并在每次操作后查询某个区间内的不同颜色数量。解决方案:由于题目中颜色种类不超过30种,可以利用线段树的懒惰更新策略来高效处理这些操作。通过懒惰标记,避免了不必要的节点更新,从而显著提高了算法的效率。此外,该方法还能有效应对大规模数据输入,确保在合理的时间内完成所有操作。 ... [详细]
  • 深入解析Android 4.4中的Fence机制及其应用
    在Android 4.4中,Fence机制是处理缓冲区交换和同步问题的关键技术。该机制广泛应用于生产者-消费者模式中,确保了不同组件之间高效、安全的数据传输。通过深入解析Fence机制的工作原理和应用场景,本文探讨了其在系统性能优化和资源管理中的重要作用。 ... [详细]
  • C++ 异步编程中获取线程执行结果的方法与技巧及其在前端开发中的应用探讨
    本文探讨了C++异步编程中获取线程执行结果的方法与技巧,并深入分析了这些技术在前端开发中的应用。通过对比不同的异步编程模型,本文详细介绍了如何高效地处理多线程任务,确保程序的稳定性和性能。同时,文章还结合实际案例,展示了这些方法在前端异步编程中的具体实现和优化策略。 ... [详细]
  • 2018 HDU 多校联合第五场 G题:Glad You Game(线段树优化解法)
    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6356在《Glad You Game》中,Steve 面临一个复杂的区间操作问题。该题可以通过线段树进行高效优化。具体来说,线段树能够快速处理区间更新和查询操作,从而大大提高了算法的效率。本文详细介绍了线段树的构建和维护方法,并给出了具体的代码实现,帮助读者更好地理解和应用这一数据结构。 ... [详细]
  • 在洛谷 P1344 的坏牛奶追踪问题中,第一问要求计算最小割,而第二问则需要找到割边数量最少的最小割。通过为每条边附加一个单位权值,可以在求解最小割时优先选择边数较少的方案,从而同时解决两个问题。这种策略不仅简化了问题的求解过程,还确保了结果的最优性。 ... [详细]
  • 2012年9月12日优酷土豆校园招聘笔试题目解析与备考指南
    2012年9月12日,优酷土豆校园招聘笔试题目解析与备考指南。在选择题部分,有一道题目涉及中国人的血型分布情况,具体为A型30%、B型20%、O型40%、AB型10%。若需确保在随机选取的样本中,至少有一人为B型血的概率不低于90%,则需要选取的最少人数是多少?该问题不仅考察了概率统计的基本知识,还要求考生具备一定的逻辑推理能力。 ... [详细]
  • 本文深入探讨了 hCalendar 微格式在事件与时间、地点相关活动标记中的应用。作为微格式系列文章的第四篇,前文已分别介绍了 rel 属性用于定义链接关系、XFN 微格式增强链接的人际关系描述以及 hCard 微格式对个人和组织信息的描述。本次将重点解析 hCalendar 如何通过结构化数据标记,提高事件信息的可读性和互操作性。 ... [详细]
  • 每日精选Codeforces训练题:1119E(贪心算法)、821C(栈模拟)和645D(拓扑排序)
    题目涉及三种不同类型的算法问题:1119E(贪心算法)、821C(栈模拟)和645D(拓扑排序)。其中,1119E的问题背景是有n种不同长度的棍子,长度分别为2^0, 2^1, …, 2^(n-1),每种棍子的数量为a[i]。任务是计算可以组成的三角形数量。根据三角形的性质,任意两边之和必须大于第三边。该问题可以通过贪心算法高效解决,通过合理选择棍子组合来最大化三角形的数量。 ... [详细]
  • 本文深入解析了JDK 8中HashMap的源代码,重点探讨了put方法的工作机制及其内部参数的设定原理。HashMap允许键和值为null,但键为null的情况只能出现一次,因为null键在内部通过索引0进行存储。文章详细分析了capacity(容量)、size(大小)、loadFactor(加载因子)以及红黑树转换阈值的设定原则,帮助读者更好地理解HashMap的高效实现和性能优化策略。 ... [详细]
  • 在探讨P1923问题时,我们发现手写的快速排序在最后两个测试用例中出现了超时现象,这在意料之中,因为该题目实际上要求的是时间复杂度为O(n)的算法。进一步研究题解后,发现有选手使用STL中的`nth_element`函数成功通过了所有测试点。本文将详细分析这一现象,并提出相应的优化策略。 ... [详细]
  • JavaScript XML操作实用工具类:XmlUtilsJS技巧与应用 ... [详细]
  • 寒假作业解析:第三周 2月12日 第7题
    尽快完成之前的练习任务!每日一练2.1 Problem A Laurenty and Shop 的题目要求是选择两条不同的路线以最小化总的等待时间。简要分析:通过对比不同路线的等待时间,可以找到最优解。此问题可以通过动态规划或贪心算法来解决,具体取决于路线的复杂性和约束条件。 ... [详细]
  • SRM 553:深入解析供应链管理系统的最新进展与应用本文详细探讨了供应链管理系统(SCM)的最新发展及其在实际应用中的影响。通过对当前技术趋势的分析,文章揭示了 SCM 在提高效率、降低成本和增强透明度方面的关键作用。此外,还介绍了几种创新的 SCM 解决方案,如区块链技术和人工智能的应用,以及这些技术如何帮助企业更好地应对市场变化和挑战。 ... [详细]
  • 在HDU 1166敌军布阵问题中,通过运用线段树数据结构,可以高效地计算指定区间的敌军数量。该算法不仅能够在限定的时间和内存条件下快速求解,还能够灵活应对动态变化的战场局势,为实时决策提供支持。 ... [详细]
  • 题目要求:给定一个整数数组,判断该数组是否为某一二叉搜索树的后序遍历结果。如果符合,则输出“是”,否则输出“否”。假设输入数组中的所有数字均不相同。此问题需要通过分析数组的特性来验证其是否满足二叉搜索树后序遍历的条件。 ... [详细]
author-avatar
莫轻松
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有