- 👋 Hi, I’m @Beast Cheng
- 👀 I’m interested in photography, hiking, landscape…
- 🌱 I’m currently learning python, javascript, kotlin…
- 📫 How to reach me --> 458290771@qq.com
喜欢《数据结构》部分笔记的小伙伴可以订阅专栏,今后还会不断更新。🧑💻
此外,《程序员必备技能》专栏日后会逐步更新,感兴趣的小伙伴可以点一下订阅、收藏、关注!🚀
谢谢大家!🙏
什么是遍历
遍历:按照某种次序把所有结点都访问一遍
层次遍历:基于树的层次特性确定的次序规则
先/中/后序遍历:基于树的递归特性确定的次序规则
二叉树的遍历
二叉树的递归特性:
- 要么是个空二叉树
- 要么就是由“根结点+左子树+右子树”组成的二叉树
如果是空二叉树,那么我们什么都不要做
如果是非空二叉树:
- 先序遍历:根左右(NLR)
- 中序遍历:左根右(LNR)
- 后序遍历:左右根(LRN)
先序遍历:ABC
中序遍历:BAC
后序遍历:BCA
先序遍历:AB
中序遍历:BA
后序遍历:BA
先序遍历:AC
中序遍历:AC
后序遍历:CA
先序遍历:A BDE CFG
中序遍历:DBE A FCG
后序遍历:DEB FGC A
先序遍历:A BDGE CF
中序遍历:DGBE A FC
后序遍历:GDEB FC A
手算练习
算数表达式的“分析树”
a + b ∗ ( c − d ) − e f a+b*(c-d)-\frac{e}{f} a+b∗(c−d)−fe
先序遍历 ——> 前缀表达式: − + a ∗ b − c d / e f -+a*b-cd/ef −+a∗b−cd/ef
中序遍历 ——> 中缀表达式(需要加界限符): a + b ∗ c − d − e / f a+b*c-d-e/f a+b∗c−d−e/f
后序遍历 ——> 后缀表达式: a b c d − ∗ + e f / − abcd-*+ef/- abcd−∗+ef/−
先序遍历的代码
先序遍历(PreOrder)的操作过程如下:
- 若二叉树为空,则什么也不做;
- 若二叉树非空:
- 访问根结点
- 先序遍历左子树
- 先序遍历右子树
typedef struct BiTNode{ElemType data;struct BiTNode *lchild, *rchild;
}BiTNode, *BiTree;// 先序遍历
void PreOrder(BiTree T){if(T != NULL){visit(T); // 访问根结点PreOrder(T->lchild); // 递归遍历左子树PreOrder(T->rchild); // 递归遍历右子树}
}
空间复杂度: O ( h ) O(h) O(h)
脑补空结点,从根结点出发,画一条路:
如果左边还有没走过的路,优先往左边走,走到路的尽头(空结点)就往回走。
如果左边没路了,就往右边走,如果左右都没路了,就往上面走
先序遍历:第一次路过时访问结点
中序遍历
中序遍历(InOrder)的操作过程如下:
- 若二叉树为空,则什么也不做;
- 若二叉树非空:
- 先序遍历左子树;
- 访问根结点;
- 先序遍历右字数
脑补空结点,从根结点出发,画一条路,如果左边还有没走的路,优先往左边走,走到路的尽头(空结点)就往回走;
如果左边没路了,就往右边走;
如果左右都没路了,就往上走。
中序遍历:第二次路过时访问结点(每个结点都会被路过3次)
后序遍历
后序遍历(InOrder)的操作过程如下:
- 若二叉树为空,则什么也不做;
- 若二叉树非空:
- 先序遍历左子树;
- 先序遍历右字数;
- 访问根结点
脑补空结点,从根结点出发,画一条路,如果左边还有没走的路,优先往左边走,走到路的尽头(空结点)就往回走;
如果左边没路了,就往右边走;
如果左右都没路了,就往上走。
后序遍历:第三次路过时访问结点(每个结点都会被路过3次)
例:求树的深度(应用)
int treeDepth(BiTree T){if (T != NULL){return 0;}else{int l = treeDepth(T->lchild);int r = treeDepth(T->rchild);// 树的深度 = Max(左子树深度,右子树深度)+ 1return l>r ? l+1 : r+1;}
}