直接上代码
import java.util.Stack; public class BinaryTree { //定义一棵二叉树,包括左子树、右子树、该节点的值和构造器 public BinaryTree lchild; public BinaryTree rchild; public char data; public BinaryTree(BinaryTree l,BinaryTree r,char data) { lchild = l; rchild = r; this.data = data; } //访问节点的函数 public void visit(BinaryTree t) { System.out.println(t.data); } /* * 递归实现二叉树的遍历都是分四步 * 1.判断树如果为空则返回 * 2.访问节点 * 3.判断左子树如果不为空则递归左子树 * 4.判断右子树不为空则递归右子树 * 前、中、后三个遍历的区别就是访问节点这一步分别实在判断左子树前,判断左子树和右子树中间,判断右子树之后*/ //递归实现前序遍历 public void pre(BinaryTree t) { if(t == null) return; visit(t); if(t.lchild != null) pre(t.lchild); if(t.rchild != null) pre(t.rchild); } //递归实现中序遍历 public void mid(BinaryTree t) { if(t == null) return; if(t.lchild != null) mid(t.lchild); visit(t); if(t.rchild != null) mid(t.rchild); } //递归实现后序遍历 public void pos(BinaryTree t) { if(t == null) return; if(t.lchild != null) pos(t.lchild); if(t.rchild != null) pos(t.rchild); visit(t); } /** * 非递归实现二叉树的遍历都是用栈实现 */ / /** * 非递归实现前序遍历 * 注意由于栈先进后出的特点,顺序是:出栈并访问,右子树不空压栈,左子树不空压栈 */ public void pre2(BinaryTree t) { Stack<BinaryTree> s = new Stack<>(); s.push(t); while(!s.isEmpty()) { BinaryTree b = s.pop(); visit(b); if(b.rchild != null) s.push(b.rchild); if (b.lchild != null) s.push(b.lchild); } } /** * 非递归实现中序遍历需要一个中间变量p代表当前树 * */ / public void mid2(BinaryTree t) { Stack<BinaryTree> s = new Stack<>(); BinaryTree p = t; while(!s.isEmpty() || p!=null) { if(p != null) { s.push(p); p = p.lchild; } else { p = s.pop(); visit(p); p = p.rchild; } } } /* 二叉树的非递归后序遍历 和前序遍历的不同是先判断一下是不是没有孩子或者左右孩子已经访问,然后才可以访问该节点 */ public List<Integer> postorderTraversal(TreeNode root) { List<Integer> res = new ArrayList<>(); if (root==null) return res; Stack<TreeNode> stack = new Stack<>(); TreeNode last = null; TreeNode cur ; stack.push(root); while (!stack.isEmpty()) { cur = stack.peek(); if ((cur.left==null&&cur.right==null)||last!=null&&(last==cur.left||last==cur.right)) { //没有孩子或者孩子已经遍历过 res.add(cur.val); last = cur; stack.pop(); } else { if (cur.right!=null) stack.push(cur.right); if (cur.left!=null) stack.push(cur.left); } } return res; } }
还有一种方法:前序遍历的时候,顺序是:根-左-右。现在只要改成:根-右-左,最后在reverse一下
注意由于stack先进后出,前序遍历的时候是先压入右,再压左,这里是先左后右
public ArrayList<Integer> postorderTraversal(TreeNode root) { if(root==null) return new ArrayList(); Stack<TreeNode> stack = new Stack(); ArrayList<Integer> res = new ArrayList(); stack.push(root); while(!stack.isEmpty()) { TreeNode cur = stack.pop(); res.add(cur.val); if(cur.left!=null) stack.push(cur.left); if(cur.right!=null) stack.push(cur.right); } Collections.reverse(res); return res; }
层序遍历:
层序遍历用BFS
迭代方法:存取节点的结构是queue队列,常用的实现类是linkedlist,不断添加节点到队列后边
递归方法:维护一个二维数组和层数,不同层的数放到不同的数组中
/* 迭代方法 */ public List<List<Integer>> levelOrder(TreeNode root) { List<List<Integer>> res = new ArrayList<>(); if (root==null) return res; Queue<TreeNode> queue = new LinkedList<>(); queue.offer(root); while (!queue.isEmpty()) { int s = queue.size(); List<Integer> cur = new ArrayList<>(); for (int i = 0; i < s; i++) { TreeNode temp = queue.poll(); cur.add(temp.val); if (temp.left!=null) queue.offer(temp.left); if (temp.right!=null) queue.offer(temp.right); } res.add(cur); } return res; }
递归方法:
List<List<Integer>> res = new ArrayList<>(); public List<List<Integer>> levelOrder(TreeNode root) { helper(root,0); return res; } public void helper(TreeNode root,int c) { if (root==null) return; if (res.size()==c) res.add(new ArrayList<>()); List<Integer> cur = res.get(c); cur.add(root.val); if (root.left!=null) helper(root.left,c+1); if (root.right!=null) helper(root.right,c+1); }