俗话说:学如逆水行舟,不进则退;心似平原走马,易放难收。这句话对程序员而言,体会更深。这行已经越来越卷了,时刻准备着,。 二叉树,在面试中,已是必备的开胃菜。而在二叉树相关的面试题目中,遍历更是常考题目。本文将从二叉树的遍历角度入手,从递归和非递归角度来分析和讲解二叉树的遍历。
遍历
❝
二叉树的遍历是指从根节点出发,按照某种次序依次访问二叉树中的所有节点,使每个节点被且仅被访问一次。
❞
二叉树的遍历,有「先序遍历」、「中序遍历」以及「后续遍历」三种。
图一
上面三种遍历方式中的先序、中序以及后序三种方式,是父节点相对于子节点来说的。如果父节点先于子节点,那么就是先序遍历。如果子节点先于父节点,那么就是后序遍历。而对于子节点来说,如果先左节点,然后是父节点,然后再是右节点,那么就是中序遍历。
如【图一】所示二叉树。其三种遍历结果如下:
先序遍历: A->B->D->E->C->F->G
中序遍历: D->B->E->A->F->C->G
后续遍历: D->E->B->F->G->C->A
为了便于理解代码,我们先定义下树的节点定义:
struct TreeNode {
TreeNode *left;
TreeNode *right;
int val;
};
先序遍历
❝
定义:先访问父节点,然后遍历左子树,最后遍历右子树。
❞
递归
相信递归遍历大家都会很容易写出来,且bugfree。因为实现代码很简单。
图二 先序遍历
在上图【图二】中,使用递归遍历,就是将其左子树和右子树也当做一棵树来进行处理。代码如下:
void PreOrder(TreeNode *root) {
if (!root) {
return;
}
// 遍历根节点(此处仅为输出,读者也可以根据实际需要进行处理,比如存储等)
std::cout << root->val << std::e