二叉树主要有两种遍历方式:
深度优先遍历:先往深走,遇到叶子节点再往回走。
广度优先遍历:一层一层的去遍历。
- 深度优先遍历
- 前序遍历(递归法,迭代法)
- 中序遍历(递归法,迭代法)
- 后序遍历(递归法,迭代法)
- 广度优先遍历
- 层次遍历(迭代法)
- 层次遍历(迭代法)
二叉树的遍历方式有递归法和迭代法
以中序遍历的迭代法为例
前序遍历
递归
class Solution {
List<Integer> result=new ArrayList<>();
public List<Integer> preorderTraversal(TreeNode root) {
Track(root);
return result;
}
private void Track(TreeNode root) {
//递归终止条件
if(root==null){
return;
}
//中
result.add(root.val);
//左
Track(root.left);
//右
Track(root.right);
}
}
迭代法
class Solution {
List<Integer> result=new ArrayList<>();
//递归
public List<Integer> preorderTraversal(TreeNode root) {
//创建一个栈
LinkedList<TreeNode> stack=new LinkedList<>();
if(root!=null){
stack.push(root);
}
while (!stack.isEmpty()){
TreeNode node=stack.peek();
if(node!=null){
stack.pop();//将该节点弹出,避免重复操作,下面再将右中左节点添加到栈中
if(node.right!=null){
stack.push(node.right);//添加右节点(空节点不入栈)
}
if(node.left!=null){
stack.push(node.left);//添加左节点(空节点不入栈)
}
stack.push(node);//添加中节点
stack.push(null);//中节点访问过,但是还没有处理,加入空节点做为标记。
}else {
stack.pop();//将空节点弹出
node=stack.peek();
stack.pop();
result.add(node.val);//加入到结果集
}
}
return result;
}
}
中序遍历
迭代法
class Solution {
List<Integer> result=new ArrayList<>();
public List<Integer> inorderTraversal(TreeNode root) {
//创建一个栈
LinkedList<TreeNode> stack=new LinkedList<>();
if(root!=null){
stack.push(root);
}
while (!stack.isEmpty()){
TreeNode node=stack.peek();
if(node!=null){
stack.pop();//将该节点弹出,避免重复操作,下面再将右中左节点添加到栈中
if(node.right!=null){
stack.push(node.right);//添加右节点(空节点不入栈)
}
stack.push(node);//添加中节点
stack.push(null);//中节点访问过,但是还没有处理,加入空节点做为标记。
if(node.left!=null){
stack.push(node.left);//添加左节点(空节点不入栈)
}
}else {
stack.pop();//将空节点弹出
node=stack.peek();
stack.pop();
result.add(node.val);//加入到结果集
}
}
return result;
}
}
后序遍历
迭代法
class Solution {
List<Integer> result=new ArrayList<>();
public List<Integer> inorderTraversal(TreeNode root) {
//创建一个栈
LinkedList<TreeNode> stack=new LinkedList<>();
if(root!=null){
stack.push(root);
}
while (!stack.isEmpty()){
TreeNode node=stack.peek();
if(node!=null){
stack.pop();//将该节点弹出,避免重复操作,下面再将右中左节点添加到栈中
stack.push(node);//添加中节点
stack.push(null);//中节点访问过,但是还没有处理,加入空节点做为标记。
if(node.right!=null){
stack.push(node.right);//添加右节点(空节点不入栈)
}
if(node.left!=null){
stack.push(node.left);//添加左节点(空节点不入栈)
}
}else {
stack.pop();//将空节点弹出
node=stack.peek();
stack.pop();
result.add(node.val);//加入到结果集
}
}
return result;
}
}
层序遍历
递归法
class Solution {
//res存储item,一个item存储一层的元素
List<List<Integer>> res = new ArrayList<>();
//deep代表深度
int deep = 0;
public List<List<Integer>> levelOrder(TreeNode root) {
checkFun(root, 0);
return res;
}
private void checkFun(TreeNode root, int deep) {
if (root == null) {
return;
}
deep++;
//当层级增加时,list的Item也增加,利用list的索引值进行层级界定
if (res.size() < deep) {
List<Integer> item = new ArrayList<>();
res.add(item);
}
res.get(deep - 1).add(root.val);
checkFun(root.left, deep);
checkFun(root.right, deep);
}
}
迭代法:
class Solution {
Queue<TreeNode> que = new LinkedList<>();
List<List<Integer>> res = new ArrayList<>();
public List<List<Integer>> levelOrder(TreeNode root) {
if (root == null) {
return res;
}
que.offer(root);
while (!que.isEmpty()) {
List<Integer> list=new ArrayList<>();
int len = que.size();
// 这里一定要使用固定大小size,不要使用que.size(),因为que.size是不断变化的
while (len>0){
TreeNode node = que.poll();
list.add(node.val);
if(node.left!=null){
que.offer(node.left);
}
if(node.right!=null){
que.offer(node.right);
}
len--;
}
res.add(list);
}
return res;
}
}