前序 | 中序 | 后序 | 层序 |
一、前序遍历
步骤:根节点->左子节点->右子节点
适用场合:在第一次遍历到节点时就执行操作,一般只是想遍历执行操作(或输出结果)可选用前序遍历。
二、中序遍历
步骤:左子节点->根节点->右子节点
适用场合:对于二分搜索树,中序遍历的操作顺序(或输出结果顺序)是符合从小到大(或从大到小)顺序的,故要遍历输出排序好的结果需要使用中序遍历。
三、后序遍历
步骤:左子节点->右子节点->根节点
适用场合:后续遍历的特点是执行操作时,肯定已经遍历过该节点的左右子节点,故适用于要进行破坏性操作的情况,比如删除所有节点。
四、层序遍历
步骤:按层,从上到下,从左到右遍历
适用场合:
五、深度优先遍历(Depth First Search)
步骤:对每一个可能的分支路径深入到不能再深入为止,而且每个节点只能访问一次。
深度优先遍历需要使用到栈这种数据结构,栈具有先进后出的特点。
如上图,我们来分析下深度优先遍历的过程。
- 首先根节点A入栈,stack(A)。
- 将A节点弹出,因为A存在 B C两个子节点,根据定义和栈特点,首先将C(右儿子)压- 入栈中,然后将B(左儿子)压入栈中,stack(C B)
- 弹出栈顶元素B节点弹出,将节点 E 和 D压入栈中,stack(C E D)。
- 弹出栈顶元素D,由于节点D只存在一个子节点H,因此H直接入栈,stack(C E H).
- 弹出栈顶元素H,元素H不存在子元素,stack(C E).
- 弹出栈顶元素E,元素E不存在子元素,stack©.
- 弹出栈顶元素C,子节点G F分别入栈,stack(G F).
- F出栈,stack(G)。
- G出栈,stack()。
- 遍历结束。
深度优先遍历的结果为: A B D H E C F G.
六、广度优先遍历(Breadth First Search)
步骤:对每一层节点依次访问,访问完一层进入下一层,而且每个节点只能访问一次。
对于上面的例子来说,广度优先遍历的 结果是:A,B,C,D,E,F,G,H(假设每层节点从左到右访问)。
广度优先遍历需要使用到队列这种数据结构,队列具有先进先出的特点。
如上图所示,我们来分析广度优先遍历的过程。
- 首先将A节点插入队列中,queue(A);
- 将A节点弹出,同时将A的子节点B,C插入队列中,此时B在队列首,C在队列尾部,queue(B,C);
- 将B节点弹出,同时将B的子节点D,E插入队列中,此时C在队列首,E在队列尾部,queue(C,D,E);
- 将C节点弹出,同时将C的子节点F,G插入队列中,此时D在队列首,G在队列尾部,queue(D,E,F,G);
- 将D节点弹出,同时将D节点的子节点H插入队列中,此时E在队列首,H在队列尾部,queue(E,F,G,H);
- E F G H分别弹出(这四个节点均不存在子节点)。
广度优先遍历结果为:A B C D E F G H