本文总结了二叉树的常见遍历方式,以及剪枝offer上的一些有关二叉树的面试题。
- 前序:中$\rightarrow$左$\rightarrow$右
- 中序:左$\rightarrow$中$\rightarrow$右
- 后序:左$\rightarrow$右$\rightarrow$中
- 层序遍历:第一层$\rightarrow$第二层$\rightarrow$第三层$\rightarrow$第n层(每层从做到右)
前序、中序、后序
树的遍历分递归实现与非递归实现:
- 递归实现:递归实现树的遍历,只需按照顺序依次递归即可,较为简单。
- 非递归实现:非递归实现需要用到STL容器,按照容器特性依次将树的节点放入容器中。
- stack容器:先进后出的特性
- 先序遍历:应按右左的顺序将一个节点的子节点放入容器中,这样可保证左节点先于右节点取出。
- 中序遍历:从根节点开始依次将节点的左节点放入栈,
- stack容器:先进后出的特性
|
|
层序遍历
层序遍历所要解决的问题很好理解,就是按二叉树从上到下,从左到右依次打印每个节点中存储的数据。
比较简单的是用队列从上到下,从左到右依次将每个数放入到队列中,然后按顺序依次打印就是想要的结果。
|
|
剑指offer树遍历题目整理
二叉树的下一个节点
- 给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针。
- 中序遍历:左中右,因此给定节点左子树已经遍历完全,下一个节点存在2中情况:
- 存在右子树:对右子树进行中序遍历
- 不存在右子树:此种情况下又分几种情况:
- 该节点为父节点的左子树:则父节点的左子树已经完全遍历,下一个应该遍历其父节点
- 该节点为父节点的右子树:父节点已经完全遍历,继续搜索父节点的父节点。
- 父节点不存在(即该节点为根节点):输出系欸但右子树。
|
|
对称二叉树
- 题目描述:请实现一个函数,用来判断一颗二叉树是不是对称的。注意,如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的。
- 依次对比吧。感觉我很喜欢写递归,对非递归方式不是很熟,接下来几题还是非递归方式联系一下。
|
|
从上到下打印二叉树
- 题目描述:从上往下打印出二叉树的每个节点,同层节点从左至右打印。
- 层序遍历,这道题是刚开始刷题的时候写的,现在看起来写的都是什么鬼,反正能AC,放这把。
|
|
把二叉树打印成多行
- 题目描述:从上到下按层打印二叉树,同一层结点从左至右输出。每一层输出一行。
- 使用队列层序遍历,难点在于如何判别是否进入下一层,分析可知,队列中只存在2层的节点,遍历上一层时将下一层节点加入队列中,本例中使用一个指针layer指向一层的最后一个节点(queue.back()),当这一层打印完时,临界状态为队列中仅存在上一层的最后一个节点与下一层的所有节点,此时,layer==queue.front(),更新layer=queue.back(),即可进入下一层的迭代。评论里也有使用queue.size()记录每层的长度的,思路其实一样。
|
|
之字形打印二叉树
- 题目描述:请实现一个函数按照之字形打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右至左的顺序打印,第三行按照从左到右的顺序打印,其他行以此类推。
- 和上题类似,使用双端队列保存节点,加入一个记录行数的变量。也可使用2个队列,一个记录奇数行,一个记录偶数行。后者在上题的基础上,得到顺序打印的res,再将res的偶数行反转。
|
|
二叉树的镜像
- 题目描述:操作给定的二叉树,将其变换为源二叉树的镜像。123456789101112二叉树的镜像定义:源二叉树8/ \6 10/ \ / \5 7 9 11镜像二叉树8/ \10 6/ \ / \11 9 7 5
|
|
二叉树的第k个节点
- 题目描述:给定一颗二叉搜索树,请找出其中的第k大的结点。例如, 5 / \ 3 7 /\ /\ 2 4 6 8 中,按结点数值大小顺序第三个结点的值为4。
- 这题找了好久的bug,无语了,还是对中序遍历不是太熟悉的缘故。其实也就是在中序遍历加上一个计数器而已。
|
|
二叉树中的某一路径
- 题目描述:输入一颗二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。
- 习惯新地就写了个递归版本,注意判断节点是否叶子节点
|
|
二叉搜索树地后序遍历结果
- 题目描述:输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。
- 这题开始没有一点思路,后来想了想后续遍历地特点才知道怎么写,后续遍历地遍历顺序是:左右中,因此数组最末尾就是树的根节点,前面一段分别是左子树、右子树,而左子树的末尾是左子树的根节点,右子树的末尾是右子树的根节点,因此可以递归求解了。如下图所示:
|
|
树的子结构
- 题目描述:输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)
- 这题没做出来,我想着在原函数上递归,后来一直超时,应该用一个新的函数的。
|
|
重建二叉树
- 题目描述:输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
- 依据前序与中序遍历的性质,前序为中左右,中序为左中右,根据前序数组的第一个节点为根节点,在中序数组中找到该节点位置,则左边为左子树,右边为右子树,递归生成整棵树。
|
|