LeetCode——树:层次遍历、前中后序遍历
目录
- 层次遍历
- 二叉树的层平均值
- 找树左下角的值
- 前中后序遍历
- 概述
- 非递归实现二叉树的前序遍历
- 非递归实现二叉树的中序遍历
- 非递归实现二叉树的后序遍历
1. 层次遍历
1. 二叉树的层平均值(LeetCode637)
- 概述
1. 给定一个非空二叉树, 返回一个由每层节点平均值组成的数组.
- 思路
- 利用广度优先搜索遍历整颗二叉树。
- 首先将它的根节点放入队列queue中,如果queue不为null,进入while循环
1. 计算当前queue的size用于待会for循环遍历,创建变量sum记录每层的和
2. queue.size.for循环,创建临时节点node存储queue弹出的元素,sum+=node.val。如果node.left或者right不为null,则加入队列
3. 退出for循环,则得到了每层的值sum,该层节点个数cnt。相除即是结果
- 代码
public static List < Double > averageOfLevels(TreeNode root) {
List<Double> ret = new ArrayList<>();
if (root==null){
return ret;
}
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()){
int cnt = queue.size();
double sum = 0;
for (int i = 0; i < cnt; i++) {
TreeNode node = queue.poll();
sum += node.val;
if (node.left !=null)
queue.offer(node.left);
if (node.right!=null)
queue.offer(node.right);
}
ret.add(sum/cnt);
}
return ret;
}
- 小结
1. 利用队列可以先遍历每一层的节点
2. 找树左下角的值(LeetCode513)
- 概述
1. 给定一个二叉树,在树的最后一行找到最左边的值。
- 思路
- 利用队列进行层次遍历,遍历过程加入队列时,先加右节点,再加左节点,这样队列每层出来的顺序就从右到左的
- 如果遍历加入队列时,是先加左节点,再加右节点,那么队列每层出来的顺序就是从左往右的
- 代码
public static int findBottomLeftValue(TreeNode root) {
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()) {
root = queue.poll();
if (root.right != null)
queue.offer(root.right);
if (root.left != null)
queue.offer(root.left);
}
return root.val;
}
3. 前中后序遍历
0. 概述
1. 层次遍历顺序:[1,2,3,4,5,6]
2. 前序遍历顺序:[1,2,4,5,3,6]
3. 中序遍历顺序:[4,2,5,1,3,6]
4. 后序遍历顺序:[4,5,2,6,3,1]
- 层次遍历使用BFS实现,利用的就是BFS一层一层遍历的特性
- 而前序,中序,后序遍历利用了DFS实现。前序,中序,后序只是对节点访问的顺序有一点不同,其他都相同
- 递归版前序,中序,后序代码
public static void preOrderRecur(TreeNode head) {
if (head == null) {
return;
}
System.out.print(head.val + " ");
preOrderRecur(head.left);
preOrderRecur(head.right);
}
public static void inOrderRecur(TreeNode head) {
if (head == null) {
return;
}
inOrderRecur(head.left);
System.out.print(head.val + " ");
inOrderRecur(head.right);
}
public static void posOrderRecur(TreeNode head) {
if (head == null) {
return;
}
posOrderRecur(head.left);
posOrderRecur(head.right);
System.out.print(head.val + " ");
}
1. 非递归实现二叉树的前序遍历
- 利用栈
- 利用栈先进后出的数据结构,可以对二叉树进行遍历。
- 先把head节点加入stack,当stack不为null时while循环stack,弹出栈顶元素,打印(因为前序遍历的顺序是:根左右,第一次遇到这个节点就打印)。
- 然后如果当前节点右孩子不为null,加入栈,左孩子不为null,加入栈,因为打印顺序是:根左右,所以加入顺序为根右左
- 代码实现
public static void preOrderUnRecur(TreeNode head) {
if (head==null){
return;
}
Stack<TreeNode> stack = new Stack<>();
stack.push(head);
while (!stack.isEmpty()){
head = stack.pop();
System.out.print(head.val+" ");
if (head.right!=null)
stack.push(head.right);
if (head.left!=null)
stack.push(head.left);
}
}
2. 非递归实现二叉树的中序遍历
- 利用栈
- 当栈不为null或者head!=null时,如果此时head!=null,则将它加入栈中,也就是将左边节点全部压入栈中
- 当head==null时,就会返回栈的最后一个元素,此时是第二次到达这个节点,所以就要打印(中序遍历:左中右,表示第二遇到这个节点就打印),然后跳到右节点
- 代码实现
public static void inOrderUnRecur(TreeNode head) {
if (head != null) {
Stack<TreeNode> stack = new Stack<>();
while (!stack.isEmpty() || head != null) {
if (head != null) {
stack.push(head);
head = head.left;
} else {
head = stack.pop();
System.out.print(head.val + " ");
head = head.right;
}
}
}
}
3. 非递归实现二叉树的后序遍历
- 利用双栈
- 后序遍历的顺序为:左右中,我们知道前序遍历:中左右,当我们在前序遍历时先添加左节点,再添加右节点时,它的顺序就会变为中右左(栈的特性),这是我们将元素添加到另一个栈,打印出的顺序就为:左右中
- 代码实现
public static void posOrderUnRecur1(TreeNode head) {
if (head!=null){
Stack<TreeNode> s1 = new Stack<>();
Stack<TreeNode> s2 = new Stack<>();
s1.push(head);
while (!s1.isEmpty()){
head = s1.pop();
s2.push(head);
if (head.left!=null)
s1.push(head.left);
if (head.right!=null)
s1.push(head.right);
}
while (!s2.isEmpty()){
System.out.print(s2.pop().val+" ");
}
}
}
补充:还有一种神奇的二叉树前中后序遍历算法——Morris遍历,有时间补充,之前总结过了,不过我也有点忘了…
二叉树的遍历(递归,非递归,Morris)