深度优先遍历
递归方式
pre
in
post
public static class Node {
int value;
Node left;
Node right;
public Node(int value) {
this.value = value;
}
}
/*中左右*/
public void recursivePreTraversal(Node root) {
if (root == null) {
return;//base
}
System.out.println(root.value);
//去打印左边-->去打印右边
recursivePreTraversal(root.left);
recursivePreTraversal(root.right);
}
/*左中右*/
public void recursiveMidTraversal(Node root) {
if (root == null) {
return;//base
}
//去打印左边
recursivePreTraversal(root.left);
System.out.println(root.value);
//去打印右边
recursivePreTraversal(root.right);
}
/*左右中*/
public void recursivePosTraversal(Node root) {
if (root == null) {
return;//base
}
//去打印左边-->去打印右边-->打印中间
recursivePreTraversal(root.left);
recursivePreTraversal(root.right);
System.out.println(root.value);
}
非递归方式(栈去模拟)
/*
* 使用非递归的方式
* 栈去模拟
* 先访问中间结点打印,压入右左结点=>先打印左子树结点再打印右支树结点=====先序pre(弹出结点的顺序和处理[打印]顺序一致)
*
* 先序:中左右==>中右左===>左右中===>逆序===>======================后序pos
*
* 先访问中间结点,先处理是左结点==>借助指针==>指针指到的地方就是处理的==>中序in
* */
public void preTraversal(Node root) {
Stack<Node> stack = new Stack<>();
stack.push(root);//访问就入栈,弹出就打印===(访问弹出顺序和处理结点的顺序高度一致)
while (!stack.isEmpty()) {
Node node = stack.pop();
System.out.println(node.value);
if (node.right != null) stack.push(node.right);//为了弹出先访问左保证和处理数据的循序一致(栈的模拟深度优先是因为往栈里添加了数据导致弹出的时候是加入的数据了)
if (node.left != null) stack.push(node.left);
}
}
public void posTraversal(Node root) {
Stack<Node> stack = new Stack<>();
Stack<Node> reverse = new Stack<>();
stack.push(root);
while (!stack.isEmpty()) {
Node node = stack.pop();
reverse.push(node);//中右左加入
if(node.left!=null) stack.push(node);
if(node.right!=null) stack.push(node);
}
while(!reverse.isEmpty()) System.out.println(reverse.pop().value);
}
public void inTraversal(Node root){
//stack处理数据,cur来决定访问循序
Stack<Node> stack=new Stack<>();
Node cur=root;//先让cur来到第一个位置
while(cur!=null||!stack.isEmpty()){//打印完了左子树,栈是null的,cur来到它的右子树
if(cur!=null){
stack.push(cur);
cur=cur.left;//遇到有左就继续,导致中和左是合并了,但是深一层的是左,弹出也是先深后浅,打印了左中,去中的右边
}else{
cur = stack.pop();//访问顺序先左后中
System.out.println(cur.value);
cur=cur.right;//只有打印了cur[中]才能轮到它的右边:访问顺序左中右
}
}
}
广度优先遍历(层次遍历)
使用变量处理发现新层
public void levelTraversal(Node head){
//nextEnd:下一层结点最后一个结点
//curEnd:本层结点的最后一个结点
//变化触发:当弹出了结点来到了curEnd,本层结束,curEnd来到nextEnd位置,nextEnd继续寻找
Node curEnd=head;
Node nextEnd=null;
Queue<Node> queue=new LinkedList<>();
queue.add(head);
while(!queue.isEmpty()){
List<Integer> level=new ArrayList<>();
Node cur = queue.poll();
//System.out.print(cur.value+" ");
if(cur.left!=null) {queue.add(cur.left);nextEnd=cur.left;}
if(cur.right!=null){queue.add(cur.right);nextEnd=cur.right;}
if(cur==curEnd) System.out.println();
}
}
用容器处理发现新层
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
//单前层的最后一个结点打印了,它的下一层结点也就已经加完了,
//每打印完一层时刻,队列的长度总会是下一层的结点数
List<List<Integer>> result=new ArrayList<>();
if(root==null) return result;
Queue<TreeNode> queue=new LinkedList<>();
queue.add(root);
while(!queue.isEmpty()){
//记录一层结点的大小
List<Integer> levelList=new ArrayList<>();
int len=queue.size();
while(len-->0){//这个len一直是本层的,忽略下层加入的
TreeNode cur=queue.poll();
levelList.add(cur.val);
if(cur.left!=null) queue.add(cur.left);
if(cur.right!=null) queue.add(cur.right);
}
result.add(levelList);//一层结束
}
return result;
}
}