层序遍历
层序遍历。听名字也知道是按层遍历。我们知道一个节点有左右节点。而每一层一层的遍历都和左右节点有着很大的关系。也就是我们选用的数据结构不能一股脑的往一个方向钻,而左右应该均衡考虑。这样我们就选用队列来实现。
- 对于队列,现进先出。从根节点的节点push到队列,那么队列中先出来的顺序是第二层的左右(假设有)。第二层每个执行的时候添加到队列,那么添加的所有节点都在第二层后面。
- 同理,假设开始pop遍历第n层的节点,每个节点会push左右两个节点进去。但是队列先进先出。它会放到队尾(下一层)。直到第n层的最后一个pop出来,第n+1层的还在队列中整齐排着。这就达到一个层序的效果。
实现的代码也很容易理解:
public void cengxu(node t) {//层序遍历Queue q1 = new ArrayDeque();if (t == null)return;if (t != null) {q1.add(t);}while (!q1.isEmpty()) {node t1 = q1.poll();if (t1.left != null)q1.add(t1.left);if (t1.right != null)q1.add(t1.right);System.out.print(t1.value + " ");}System.out.println();}
前中后序遍历(递归)
其实这种就是一个类似dfs的思想。用递归实现。前面有很详细的介绍递归算法。我们采用的三序遍历是采用同一个递归。并且大家也都直到递归是一个有来有回的过程。三序遍历只是利用了递归中的来回过程中不同片段截取输出,而达到前(中、后序遍历的结果)。
前序递归
前序的规则就是根结点 ---> 左子树 ---> 右子树.我们在调用递归前进行节点操作。对于前序,就是先访问(输出)该节点。而递归左,递归右侧,会优先递归左侧。直到没有左节点。才会停止。访问次序大致为:
public void qianxu(node t)// 前序递归 前序遍历:根结点 ---> 左子树 ---> 右子树{if (t != null) {System.out.print(t.value + " ");// 当前节点qianxu(t.left);qianxu(t.right);}}
中序递归
有了前序的经验,我们就很好利用递归实现中序遍历。中序遍历的规则是:左子树---> 根结点 ---> 右子树。所以我们访问节点的顺序需要变。
- 我们直到递归是来回的过程,对于恰好有两个子节点(子节点无节点)的节点来说。只需要访问一次左节点,访问根,访问右节点。即可。
- 而如果两侧有节点来说。每个节点都要满足中序遍历的规则。我们从根先访问左节点。到了左节点这儿左节点又变成一颗子树,也要满足中序遍历要求。所以就要先访问左节点的左节点(如果存在)。那么如果你这样想,规则虽然懂了。但是也太复杂了。那么我们借助递归。因为它的子问题和根节点的问题一致,只是范围减小了。所以我们使用递归思想来解决。
- 那么递归的逻辑为:考虑特殊情况(特殊就直接访问)不进行递归否则递归的访问左子树(让左子树执行相同函数,特殊就停止递归输出,不特殊就一直找下去直到最左侧节点。)——>输出该节点—>递归的访问右子树.
代码为:
public void zhongxu(node t)// 中序遍历 中序遍历:左子树---> 根结点 ---> 右子树{if (t != null) {zhongxu(t.left);System.out.print(t.value + " ");// 访问完左节点访问当前节点zhongxu(t.right);}}
后序递归
同理,有了前面的分析,后续就是左子树 ---> 右子树 ---> 根结点
public void houxu(node t)// 后序遍历 后序遍历:左子树 ---> 右子树 ---> 根结点{if (t != null) {houxu(t.left);houxu(t.right);System.out.print(t.value + " "); // 访问玩左右访问当前节点}}