經過遞歸方式遍歷二叉樹很是簡單,只須要調整訪問左子樹、右子樹、當前結點這三個語句的順序,就能夠實現三種遍歷,可是畢竟須要遞歸調用,運算速度不及迭代方式、並且在面試中也會常常遇到,本問簡單介紹幾種迭代實現方式。面試
一、 直接利用棧的FILO特性實現,後訪問的先入棧post
public void preorder(TreeNode root){ if(root == null) return; LinkedList<TreeNode> stack = new LinkedList<>(); stack.push(root); while(!stack.isEmpty()){ root = stack.pop(); visit(root); if(root.right != null) stack.push(root.right); if(root.left != null) stack.push(root.left); } }
每次先將右子樹壓棧,那麼出棧時先訪問左子樹。code
二、 dfs思想,優先向左子樹訪問,而後每次出棧後,再訪問右子樹遞歸
public void preorderTraversal(TreeNode root) { LinkedList<TreeNode> stack = new LinkedList<>(); while(root != null || !stack.isEmpty()){ while(root != null){ stack.push(root); visit(root); root = root.left; } root = stack.pop(); root = root.right; } }
一、 和前面前序遍歷dfs思想同樣,只是訪問結點的位置變了it
public void inorderTraversal(TreeNode root) { LinkedList<TreeNode> stack = new LinkedList<>(); while(root != null || !stack.isEmpty()){ while(root != null){ stack.push(root); root = root.left; } root = stack.pop(); visit(root); root = root.right; } return ans; }
二、 思想同1,寫法稍有不一樣List
public void inorderTraversal(TreeNode root) { LinkedList<TreeNode> stack = new LinkedList<>(); while(root != null || !stack.isEmpty()){ if(root != null){ stack.push(root); root = root.left; }else{ root = stack.pop(); visit(root); root = root.right; } } }
三、若是能夠改變數的結構,那麼能夠每次把左右子樹壓棧後,將當前結點左右子結點設爲空二叉樹
public void inorderTraversal(TreeNode root) { LinkedList<TreeNode> stack = new LinkedList<>(); if(root == null) return ; stack.push(root); while(!stack.isEmpty()){ root = stack.pop(); if(root.left == null && root.right == null){ visit(root); continue; } if(root.right != null) stack.push(root.right); stack.push(root); if(root.left != null) stack.push(root.left); root.left = null; root.right = null; } }
一、能夠利用同前序遍歷的思想,依次訪問結點、左子樹、右子樹,不過由於當前結點須要最後訪問,全部能夠把訪問結果放在棧中,而後當遍歷完成後從棧頂開始訪問。rsa
public List<Integer> postorderTraversal(TreeNode root) { LinkedList<TreeNode> stack = new LinkedList<>(); LinkedList<Integer> ans = new LinkedList<>(); while(root != null || !stack.isEmpty()){ while(root != null){ stack.push(root); ans.offerFirst(root.val); root = root.right; } root = stack.pop(); root = root.left; } return ans; }
二、一樣也能夠直接將左右子樹壓棧,結果也壓榨,同preorder 1遍歷
public List<Integer>preorder(TreeNode root){ LinkedList<Integer> ans = new LinkedList<>(); if(root == null) return ans; LinkedList<TreeNode> stack = new LinkedList<>(); stack.push(root); while(!stack.isEmpty()){ root = stack.pop(); ans.offerFirst(root.val); if(root.right != null) stack.push(root.right); if(root.left != null) stack.push(root.left); } }
三、同中序遍歷3,若是能夠修改樹,那麼能夠每次把左右子樹壓棧後,將當前結點左右子結點設爲空vi
public void inorderTraversal(TreeNode root) { LinkedList<TreeNode> stack = new LinkedList<>(); if(root == null) return ; stack.push(root); while(!stack.isEmpty()){ root = stack.pop(); if(root.left == null && root.right == null){ visit(root); continue; } if(root.right != null) stack.push(root.right); if(root.left != null) stack.push(root.left); stack.push(root); root.left = null; root.right = null; } }