二叉樹前序中序後序遍歷的非遞歸方法

二叉樹遍歷

經過遞歸方式遍歷二叉樹很是簡單,只須要調整訪問左子樹、右子樹、當前結點這三個語句的順序,就能夠實現三種遍歷,可是畢竟須要遞歸調用,運算速度不及迭代方式、並且在面試中也會常常遇到,本問簡單介紹幾種迭代實現方式。面試

前序遍歷(preorder)

一、 直接利用棧的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;
        }
    }

中序遍歷(inorder)

一、 和前面前序遍歷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;
            
        }
    }

後序遍歷(postorder)

一、能夠利用同前序遍歷的思想,依次訪問結點、左子樹、右子樹,不過由於當前結點須要最後訪問,全部能夠把訪問結果放在棧中,而後當遍歷完成後從棧頂開始訪問。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;
            
        }
    }
相關文章
相關標籤/搜索