二叉树结点结构
1 2 3 4 5 6 7 8 9 10 11 12
| public class TreeNode { int val; TreeNode left; TreeNode right; TreeNode(int x){ val=x; } @Override public String toString(){ return "val: "+val; } }
|
访问函数
1 2 3
| public void visit(TreeNode node){ System.out.print(node.val+" "); }
|
前序遍历
递归实现
1 2 3 4 5 6
| public void preOrderRecursion(TreeNode node){ if(node==null)return; visit(node); preOrderRecursion(node.left); preOrderRecursion(node.right); }
|
非递归实现
使用栈:根节点出栈,右节点入栈,左节点入栈
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| class Solution { public List<Integer> preorderTraversal(TreeNode root) { List<Integer> result=new ArrayList<Integer>(); Stack<TreeNode> preStack=new Stack<TreeNode>(); if(root==null)return result; preStack.push(root); while(!preStack.isEmpty()){ TreeNode nodeNow=preStack.pop(); result.add(nodeNow.val); if(nodeNow.right!=null)preStack.push(nodeNow.right); if(nodeNow.left!=null)preStack.push(nodeNow.left); } return result; } }
|
中序遍历
非递归实现
使用栈+双层循环:内层循环不停寻找左孩子并入栈,直到没有左孩子;外层循环每次pop出栈顶元素,并都把右孩子(如果有)入栈。
注意一点:外层循环的判断条件是或,即只要栈非空或者结点有右孩子,就继续循环。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| class Solution { public List<Integer> inorderTraversal(TreeNode root) { List<Integer> result=new ArrayList<Integer>(); Stack<TreeNode> inStack=new Stack<TreeNode>(); TreeNode currentNode=root; while(!inStack.isEmpty()||currentNode!=null){ while(currentNode!=null){ inStack.push(currentNode); currentNode=currentNode.left; } currentNode=inStack.pop(); result.add(currentNode.val); currentNode=currentNode.right; } return result; } }
|
后序遍历
非递归实现
使用一个栈和一个hashmap,hashmap记录节点是否被访问过。
四种情况访问这个节点:
没有左右孩子
只有左孩子且左孩子已被访问
只有右孩子且右孩子已被访问
有左右孩子且左右孩子都被访问
左孩子未被访问,则不断把左孩子入栈
右孩子未被访问,把这个右孩子入栈
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| class Solution { public List<Integer> postorderTraversal(TreeNode root) { List<Integer> result=new ArrayList<Integer>(); Stack<TreeNode> postStack=new Stack<TreeNode>(); Map<TreeNode,Integer> visitedNode=new HashMap<TreeNode,Integer>(); if(root==null)return result; postStack.push(root); while(!postStack.isEmpty()){ TreeNode currentNode=postStack.peek(); if( (currentNode.left==null&¤tNode.right==null)|| (currentNode.left==null&¤tNode.right!=null&&visitedNode.containsKey(currentNode.right))|| (currentNode.right==null&¤tNode.left!=null&&visitedNode.containsKey(currentNode.left))|| (currentNode.right!=null&¤tNode.left!=null&&visitedNode.containsKey(currentNode.left)&&visitedNode.containsKey(currentNode.right))){ result.add(currentNode.val); visitedNode.put(currentNode,1); postStack.pop(); continue; } if(currentNode.left!=null&&(!visitedNode.containsKey(currentNode.left))){ while(currentNode.left!=null){ postStack.push(currentNode.left); currentNode=currentNode.left; } } if(currentNode.right!=null&&(!visitedNode.containsKey(currentNode.right))){ postStack.push(currentNode.right); } } return result; } }
|
层序遍历
非递归实现
- 使用队列,每次结点出栈后将左右结点依次入队
- 使用变量
levelNum
保存当前层的结点个数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| class Solution { public List<List<Integer>> levelOrder(TreeNode root) { List<List<Integer>> result=new ArrayList<>(); Queue<TreeNode> nodeQueue=new LinkedList<TreeNode>(); if(root==null)return result; nodeQueue.offer(root); int levelNum=1; while(!nodeQueue.isEmpty()){ List<Integer> levelList=new ArrayList<>(); while(levelNum!=0){ TreeNode tmp=nodeQueue.poll(); if(tmp.left!=null){ nodeQueue.offer(tmp.left); } if(tmp.right!=null){ nodeQueue.offer(tmp.right); } levelList.add(tmp.val); levelNum--; } result.add(levelList); levelNum=nodeQueue.size(); } return result; } }
|