二叉树是一种常用的数据结构,常用的遍历方法有先序遍历,中序遍历,后序遍历和层次遍历。
定义二叉树节点
public class TreeNode{
int val;
TreeNode left;
TreeNode right;
TreeNode(int val){
this.val=val;
}
public static void create(TreeNode root){
TreeNode a = new TreeNode(2);
TreeNode b = new TreeNode(3);
TreeNode c = new TreeNode(4);
TreeNode d = new TreeNode(5);
TreeNode e = new TreeNode(6);
TreeNode f = new TreeNode(7);
TreeNode g = new TreeNode(8);
TreeNode h = new TreeNode(9);
TreeNode i = new TreeNode(10);
root.left=a;root.right=b;
a.left=c; a.right=d;
b.left=e; b.right=f;
d.left=g; e.right=h;
h.left=i;
}
}
/**
* 建造如下二叉树,用于测试
* 1
* / \
* 2 3
* /\ / \
* 4 5 6 7
* / \
* 8 9
* /
* 10
*
*/
一、先序遍历
基本思想:先访问根节点,再访问左子树,再访问右子树;根节点——>左子树——>右子树
- 递归
public static void preOrder(TreeNode root){
if(root!=null){
System.out.print(root.val+" ");
preOrder(root.left);
preOrder(root.right);
}
}//1 2 4 5 8 3 6 9 10 7
- 非递归
非递归用循环和栈实现,先遍历根节点,然后往左子树循环并入栈,遇到空即左子树遍历完了,出栈返回父节点,往右子树遍历
public static void preOrder1(TreeNode root){
LinkedList<TreeNode> stack = new LinkedList<>();
TreeNode node = root;
while(!stack.isEmpty()||node!=null){
if(node!=null){
System.out.print(node.val+" ");
stack.push(node);
node=node.left;
}else{
TreeNode node2 = stack.pop();
node = node2.right;
}
}
}//1 2 4 5 8 3 6 9 10 7
二、中序遍历
基本思想:先访问左子树,再访问根节点,再访问右子树;左子树——>根节点——>右子树
- 递归
public static void inOrder(TreeNode root){
if(root!=null){
inOrder(root.left);
System.out.print(root.val+" ");
inOrder(root.right);
}
}//4 2 8 5 1 6 10 9 3 7
- 非递归
跟先序遍历有点不同,这次要遍历到最左端(最靠左的节点)才开始输出
public static void inOrder1(TreeNode root){
LinkedList<TreeNode> stack = new LinkedList();
TreeNode node = root;
while(node!=null||!stack.isEmpty()){
if(node!=null){
stack.push(node);
node=node.left;
}else{
TreeNode node2 = stack.pop();
System.out.print(node2.val+" ");
node = node2.right;
}
}
}//4 2 8 5 1 6 10 9 3 7
三、后序遍历
基本思想:先访问左子树,再访问右子树,再访问根节点;左子树——>右子树——>根节点
- 递归
public static void postOrder(TreeNode root){
if(root!=null){
postOrder(root.left);
postOrder(root.right);
System.out.print(root.val+" ");
}
}//4 8 5 2 10 9 6 7 3 1
- 非递归
后序遍历也是先要往左遍历,当遇到空时,返回父节点即出栈,若此节点右子树不为空则要先往右子树遍历,此时把此节点用数组保存起来,表示该节点的右子树已经访问过了,避免从右子树返回父节点时发现此节点有右子树而又往已经遍历的右子树遍历,造成死循环,这样数组保存起来的节点再次遇到就可以直接输出了。
public static void postOrder1(TreeNode root){
LinkedList<TreeNode> stack = new LinkedList<>();
List<TreeNode> vis = new ArrayList<>();
TreeNode node = root;
while(!stack.isEmpty()||node!=null){
if(node!=null){
stack.push(node);
node=node.left;
}else{
TreeNode node2 = stack.pop();
if(node2.right!=null){
if(!vis.contains(node2)){
stack.push(node2);
node = node2.right;
vis.add(node2);
}else {
System.out.print(node2.val + " ");
}
}else{
System.out.print(node2.val+" ");
node = node2.right;
}
}
}
}//4 8 5 2 10 9 6 7 3 1
四、层次遍历
这是leetcode上的题目 :二叉树的层次遍历
输出层次遍历并按层次输出。
class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
if(root==null) return new ArrayList<>();
LinkedList<TreeNode> queue = new LinkedList<TreeNode>();
queue.offer(root);
List<List<Integer> > list = new ArrayList<List<Integer> >();
while(!queue.isEmpty()){
int cnt = queue.size();
ArrayList<Integer> temp = new ArrayList<>();
while(cnt>0){
TreeNode node = queue.poll();
temp.add(node.val);
if(node.left!=null)
queue.offer(node.left);
if(node.right!=null)
queue.offer(node.right);
cnt--;
}
list.add(temp);
}
return list;
}
}