二叉树遍历往往会使用到递归,往往递归的方法是容易实现的,如果是非递归实现一般都是可以用栈或者队列实现。
二叉树定义
//Definition for a binary tree node.
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
}
前序中序后序三种遍历的三种思想:
前序:根-左-右
中序:左-根-右
后序:左-右-根
三种遍历的顺序不同在代码中的体现往往就是顺序的一些不同。
层次遍历一般就是从根节点开始按层依次,与广度优先搜索类似。
二叉树前序遍历
前序遍历顺序是根-左-右
递归实现
List<Integer> list=new ArrayList<>();
public List<Integer> preorderTraversal(TreeNode root) {
if(root!=null){
//根-左-右
result.add(root.val);
preorderTraversal(root.left);
preorderTraversal(root.right);
}
return result;
}
非递归实现
public List<Integer> preorderTraversal(TreeNode root) {
Stack<TreeNode> stack=new Stack<>();
ArrayList<Integer> list=new ArrayList<>();
while(!stack.isEmpty()||root!=null){
//root不为空就添加到结果集并入栈,再指向左节点
if(root!=null){
list.add(root.val);
stack.push(root);
root=root.left;
}else{//root为空就出栈,指向右节点
TreeNode pop=stack.pop();
root=pop.right;
}
}
return list;
}
二叉树中序遍历
中序遍历的顺序是左-根-右
递归实现
List<Integer> list=new ArrayList<>();
public List<Integer> preorderTraversal(TreeNode root) {
if(root!=null){
//左-根-右
preorderTraversal(root.left);
list.add(root.val)
preorderTraversal(root.right);
}
return result;
}
非递归实现
public List<Integer> inorderTraversal(TreeNode root) {
ArrayList<Integer> list = new ArrayList<>();
Stack<TreeNode> stack = new Stack<>();
while(root!=null||!stack.isEmpty()){
while(root!=null){
stack.push(root);//根结点先进后出
root = root.left;//遍历左结点
}
root = stack.pop();//遍历到最左结点先出栈
list.add(root.val);
root = root.right;//遍历右节点
}
return list;
}
二叉树后序遍历
后序遍历的顺序是左-根-右
递归实现
List<Integer> list=new ArrayList<>();
public List<Integer> preorderTraversal(TreeNode root) {
if(root!=null){
//左-右=根
preorderTraversal(root.left);
preorderTraversal(root.right);
list.add(root.val)
}
return list;
}
非递归实现
这里用到了链表,且链表采用头插法,这样就可以将先插入的根结点致于末尾,一般往往不同的打印顺序可以使用不同的插入方法实现。
PS:也可以直接使用动态数组,在加入数值时每次都从第一个位置加入,也可以满足链表的逆序。
public List<Integer> inorderTraversal(TreeNode root) {
Stack<TreeNode> stack=new Stack<>();
LinkedList<Integer> list=new LinkedList<>();
if(root==null)
return list;
//从上到下,从左至右将节点入栈,依次出栈,得到的结果反向输出即可
stack.add(root);
while(!stack.isEmpty()){
TreeNode pop=stack.pop();
//总是将结果添加到头部,相当于反转了结果
list.addFirst(pop.val);
if(pop.left!=null)
stack.push(pop.left);
if(pop.right!=null)
stack.push(pop.right);
}
return list;
}
二叉树层次遍历
二叉树层次遍历可以采用队列先进先出的思想实现,每次只让一层结点入队,并依次出队,同时将该结点的左右结点入队。
简单层次遍历(所有结点放入一个list)
public ArrayList<Integer> PrintFromTopToBottom(TreeNode root) {
ArrayList<Integer> list=new ArrayList<>();
Queue<TreeNode> queue=new LinkedList<>();
if(root!=null) queue.add(root);
while(!queue.isEmpty()){
TreeNode node=queue.poll();
list.add(node.val);
if(node.left!=null) queue.add(node.left);
if(node.right!=null) queue.add(node.right);
}
return list;
}
层次遍历(按层输出)
多一个队列元素计数标志(还有按之字形打印二叉树的面试题,也只是元素插入顺序不同而已)具体而已
public ArrayList<ArrayList<Integer> > PrintFromTopToBottom(TreeNode Root) {
ArrayList<ArrayList<Integer>> res=new ArrayList<>();
if(Root==null) return res;
Queue<TreeNode> queue=new LinkedList<>();
queue.add(Root);
while(!queue.isEmpty()){
int count=queue.size();
ArrayList<Integer> list=new ArrayList<>();
while(count>0){
TreeNode node=queue.poll();
list.add(node.val);
if(node.left!=null) queue.add(node.left);
if(node.right!=null) queue.add(node.right);
count--;
}
res.add(list);
}
return res;
}