二叉樹的非遞歸遍歷和遞歸遍歷

前言

二叉樹的遍歷有前序遍歷、中序遍歷、後續遍歷、層序遍歷。然後我們分別實現一下各種遍歷的遞歸與非遞歸的方式,樹節點定義如下:

class TreeNode {
        int val;
        TreeNode left;
        TreeNode right;
        TreeNode(int x) { val = x; }

    }
前序遍歷

前序遍歷是指我們的二叉樹先遍歷root節點,然後遍歷左節點,最後是右節點

遞歸
public void preOrder(TreeNode root){
        if (root == null){
            return;
        }
        //輸出當前節點的值
        System.out.println(root.val);
        //遍歷做子樹
        preOrder(root.left);
        //遍歷右子樹
        preOrder(root.right);
    }
非遞歸
public void preOrder(TreeNode root){
        if (root == null){
            return;
        }
        //藉助棧先進後出的特性,先將root.right存入,在存入root.left
        Stack<TreeNode> stack = new Stack<>();
        stack.push(root);
        while (!stack.isEmpty()){
            TreeNode node = stack.pop();
            System.out.println(node.val);
            if (node.right != null){
                stack.push(node.right);
            }
            if (node.left != null){
                stack.push(node.left);
            }
        }
    }
中序遍歷
遞歸
public void midOrder(TreeNode root){
        if (root == null){
            return;
        }
        //遍歷做子樹
        preOrder(root.left);
        //輸出當前節點的值
        System.out.println(root.val);
        //遍歷右子樹
        preOrder(root.right);
    }
非遞歸
public void midOrder(TreeNode root){
        if (root == null){
            return;
        }
        Stack<TreeNode> stack = new Stack<>();
        do {
            //如果左節點一直有,一直壓棧
            while (root != null){
                stack.push(root);
                root = root.left;
            }
            //出棧,判斷是否有右孩子,如果有,就要繼續壓棧
            TreeNode node = stack.pop();
            System.out.println(node.val);
            if (node.right != null){
                root = node.right;
            }
        }while (root!= null || !stack.isEmpty());
    }
後序遍歷
遞歸
public void afterOrder(TreeNode root){
        if (root == null){
            return;
        }

        //遍歷做子樹
        preOrder(root.left);
        //遍歷右子樹
        preOrder(root.right);
        //輸出當前節點的值
        System.out.println(root.val);
    }

非遞歸
public void afterOrder(TreeNode root){
        if (root == null){
            return;
        }
        //藉助兩個棧來實現,因爲要先遍歷右孩子才能root節點,所以root節點要在s2的最底部
        Stack<TreeNode> s1 = new Stack<>();
        Stack<TreeNode> s2 = new Stack<>();
        s1.push(root);
        while (!s1.isEmpty()){
            TreeNode node = s1.pop();
            if (node.left != null){
                s1.push(node.left);
            }
            if (node.right != null){
                s1.push(node.right);
            }
            s2.push(node);
        }
       while (!s2.isEmpty()){
           System.out.println(s2.pop().val);
       }

    }
層序遍歷

層序遍歷是指將二叉樹的節點一層一層的遍歷出來,這裏我假設將節點存入list,採用BFS的方式遍歷節點。

public List<List<Integer>> levelOrder(TreeNode root) {
		//存訪每一層的結果
        List<List<Integer>> lists = new ArrayList<>();
        if (root == null){
            return lists;
        }
        //藉助隊列存放每一層的節點
        Queue<TreeNode> queue = new LinkedBlockingQueue<>();
        queue.add(root);
        while (!queue.isEmpty()){
            List<Integer> list = new ArrayList<>();
            int size = queue.size();
            //獲取當前隊列中的所有節點,然後將每個節點的左右孩子放入隊列,以提供下層循環輸出
            for (int i = 0; i < size; i++) {
                TreeNode node = queue.poll();
                list.add(node.val);
                if (node.left != null){
                    queue.add(node.left);
                }
                if (node.right != null){
                    queue.add(node.right);
                }
            }
            //每一層的list存入lists
            lists.add(list);
        }
        return lists;
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章