二叉树的非递归遍历(背诵版、Java)
在程序员的技术面试中,对二叉树的非递归遍历是一个高频考点。本篇文章以备战面试为目的,提供简单易懂、方便记忆的算法模板。1、背景介绍 1.1、二叉树的定义 Java语言描述的二叉树的数据结构如下:
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x;
}
}
1.2、二叉树的层次遍历 在讲解树的前中后序遍历的非递归版之前,首先介绍一下大家非常熟悉的二叉树的层次遍历。
题目描述:给定一个二叉树,返回其按层次遍历的节点值。 (即逐层地,从左到右访问所有节点)。解法
题目来源:leetcode 102题
可以通过队列来实现二叉树的层次遍历。在Java中队列通过接口Queue定义,LinkedList是Queue的实现类。
当只需要按序输出不考虑层次的时候:
public void levelOrder(TreeNode root) {
if (root == null) return;
Queue queue = new LinkedList<>();
queue.add(root);
//根节点入队while (!queue.isEmpty()) {
TreeNode t = queue.poll();
//出队队首元素
System.out.println(t.val);
if (t.left != null) queue.add(t.left);
//先左孩子入队
if (t.right != null) queue.add(t.right);
//再右孩子入队
}
}
题目要求按层保存再二维列表中:
public List> levelOrder(TreeNode root) {
List> result = new ArrayList<>();
if (root == null) return result;
Queue queue = new LinkedList<>();
queue.add(root);
//根节点入队while (!queue.isEmpty()) {
int size = queue.size();
//记录当前层节点数量
ArrayList subList = new ArrayList<>();
//记录当前层节点数据
for (int i = 0;
i < size;
i++) {
TreeNode t = queue.poll();
//出队队首元素
subList.add(t.val);
if (t.left != null) queue.add(t.left);
//先左孩子入队
if (t.right != null) queue.add(t.right);
//再右孩子入队
}
result.add(subList);
}return result;
}
2、前序遍历的非递归算法
题目描述:给定一个二叉树,返回它的 前序 遍历。实现如下:
题目来源:leetcode 144题
在熟练层次遍历的基础上,记忆前序遍历的非递归算法显得十分简单。
记忆诀窍:队列换栈,左右颠倒。
队列换栈,就是将层次遍历使用到的队列换成栈,相应的入队出队操作也要换成入栈出栈操作。
左右颠倒,就是将层次遍历先左后右的入队操作,改成先右后左的入栈操作。
public void preorderTraversal(TreeNode root) {
if (root == null) return;
Stack s = new Stack<>();
s.push(root);
//根节点入队while (!s.isEmpty()) {
TreeNode t = s.pop();
//出栈栈顶元素
System.out.println(t.val);
if (t.right != null) s.push(t.right);
//先右孩子入栈
if (t.left != null) s.push(t.left);
//再左孩子入栈}
}
3、后序遍历的非递归算法
题目描述:给定一个二叉树,返回它的 后序 遍历。将前序遍历转变成后序遍历的方式:
题目来源:leetcode 145题
在熟练前序遍历的基础上,记忆后序遍历的非递归算法显得十分简单。
记忆诀窍:左右颠倒,结果逆置
前序遍历的顺序是:根 → 左 → 右
后序遍历的顺序是:左 → 右 → 根
1、左右颠倒:将前序遍历左右孩子的顺序颠倒,则为:根 → 右 → 左。
2、结果逆置:再将整个遍历结果逆序,则为:左 → 右 → 根。
3、这时的遍历顺序已经和后序遍历的顺序一致
public void postorderTraversal(TreeNode root) {
if (root == null) return;
Stack s1 = new Stack<>();
Stack s2 = new Stack<>();
//通过栈将结果逆置
s1.push(root);
while (!s1.isEmpty()) {
TreeNode t = s1.pop();
s2.push(t);
if (t.left != null) s1.push(t.left);
if (t.right != null) s1.push(t.right);
}while (!s2.isEmpty()) {
System.out.println(s2.pop().val);
}
}
4、中序遍历的非递归算法
【二叉树的非递归遍历(背诵版、Java)】题目描述:给定一个二叉树,返回它的中序 遍历。
题目来源:leetcode 94题
public void inorderTraversal_2(TreeNode root) {
Stack s = new Stack<>();
TreeNode curr = root;
//指针指向根while (curr != null || !s.isEmpty()) {
while (curr != null) {//指针入栈并左移
s.push(curr);
curr = curr.left;
}
TreeNode pop = s.pop();
System.out.println(pop.val);
curr = pop.right;
}
}
推荐阅读
- 热闹中的孤独
- JAVA(抽象类与接口的区别&重载与重写&内存泄漏)
- 放屁有这三个特征的,请注意啦!这说明你的身体毒素太多
- 一个人的旅行,三亚
- 布丽吉特,人生绝对的赢家
- 慢慢的美丽
- 尽力
- 一个小故事,我的思考。
- 家乡的那条小河
- 《真与假的困惑》???|《真与假的困惑》??? ——致良知是一种伟大的力量