1. 程式人生 > >二叉樹的遍歷(遞迴與非遞迴版本)

二叉樹的遍歷(遞迴與非遞迴版本)

最近在寫關於二叉樹方面的題目的時候,總是會用到二叉樹的各種遍歷,所以在這裡將自己寫的各種遍歷,都記錄下來.

遞迴部分:
首先二叉樹的遞迴程式碼是比較簡單的,而且前序,中序和後序遍歷程式碼幾乎一樣, 只是列印節點值的輸出語句的位置不一樣.
可以遞迴部分,對於二叉樹中節點的遍歷順序是一樣的, 都是先遍歷當前節點,然後遍歷當前節點的左子樹,然後是右子樹, 然後在遍歷節點的過程, 選擇輸出的節點值的時機.

非遞迴部分:
其實思想還是參考遞迴部分, 只是將遞迴遍歷節點部分, 變成了使用棧來存放遍歷的節點, 然後選擇列印節點的值的時機

以下是程式碼部分

import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;

/**
 * author: zzw5005
 * date: 2018/11/24 9:57
 */


public class TraversalBST {
    //遞迴版本的二叉樹遍歷
    public static void preOrder(TreeNode root){
        if(root == null){
            return;
        }

        System.out.print(root.val + " ");
        preOrder(root.left);
        preOrder(root.right);
    }

    public static void inOrder(TreeNode root){
        if(root == null){
            return;
        }

        inOrder(root.left);
        System.out.print(root.val + " ");
        inOrder(root.right);
    }

    public static void posOrder(TreeNode root){
        if(root == null){
            return;
        }

        posOrder(root.left);
        posOrder(root.right);
        System.out.print(root.val + " ");
    }

    //非遞迴版本的二叉樹遍歷
    public static void preOrder1(TreeNode root){
        Stack<TreeNode> stack = new Stack<>();

        while(!stack.isEmpty() || root != null){
            while(root != null){
                System.out.print(root.val + " ");
                stack.push(root);
                root = root.left;
            }

            if(!stack.isEmpty()){
                root = stack.pop();
                root = root.right;
            }
        }
    }

    public static void inOrder1(TreeNode root){
        Stack<TreeNode> stack = new Stack<>();

        while(!stack.isEmpty() || root != null){
            while(root != null){
                stack.push(root);
                root = root.left;
            }
            if(!stack.isEmpty()){
                root = stack.pop();
                System.out.print(root.val + " ");
                root = root.right;
            }
        }
    }

    public static void posOrder1(TreeNode root){
        Stack<TreeNode> stack1 = new Stack<>();
        Stack<Integer> stack2 = new Stack<>();

        while(!stack1.isEmpty() || root != null){
            while(root != null){
                stack1.push(root);
                stack2.push(0);
                root = root.left;
            }

            while(!stack1.isEmpty() && stack2.peek() == 1){
                stack2.pop();
                System.out.print(stack1.pop().val + " ");
            }

            if(!stack1.isEmpty()){
                stack2.pop();
                stack2.push(1);
                root = stack1.peek();
                root = root.right;
            }
        }

    }

    public static void levOrder(TreeNode root){
        if(root == null){
            return;
        }

        Queue<TreeNode> queue = new LinkedList<>();
        queue.add(root);

        while(!queue.isEmpty()){
            root = queue.poll();
            System.out.print(root.val + " ");

            if(root.left != null){
                queue.add(root.left);
            }

            if(root.right != null){
                queue.add(root.right);
            }
        }
    }
    
    public static class TreeNode {
        int val = 0;
        TreeNode left = null;
        TreeNode right = null;

        public TreeNode(int val) {
            this.val = val;
        }
    }

    public static void main(String[] args) {
        //樹
        TreeNode root = new TreeNode(8);
        root.left = new TreeNode(6);
        root.right = new TreeNode(10);

        //root.left = new TreeNode(6);
        root.left.left = new TreeNode(5);
        root.left.right = new TreeNode(7);

        //root.left.right = new TreeNode(10);
        root.right.left = new TreeNode(9);
        root.right.right = new TreeNode(11);

        System.out.println("遞迴版本的二叉樹遍歷 : ");
        System.out.print("preOrder : ");
        preOrder(root);
        System.out.println();

        System.out.print("inOrder  : ");
        inOrder(root);
        System.out.println();

        System.out.print("posOrder : ");
        posOrder(root);
        System.out.println("\n");


        System.out.println("非遞迴版本的二叉樹遍歷 : ");
        System.out.print("preOrder1 : ");
        preOrder1(root);
        System.out.println();

        System.out.print("inOrder1  : ");
        inOrder1(root);
        System.out.println();

        System.out.print("posOrder1 : ");
        posOrder1(root);
        System.out.println();

        System.out.print("levOrder  : ");
        levOrder(root);
        System.out.println();
    }
}

輸出的結果

遞迴版本的二叉樹遍歷 : 
preOrder : 8 6 5 7 10 9 11 
inOrder  : 5 6 7 8 9 10 11 
posOrder : 5 7 6 9 11 10 8 

非遞迴版本的二叉樹遍歷 : 
preOrder1 : 8 6 5 7 10 9 11 
inOrder1  : 5 6 7 8 9 10 11 
posOrder1 : 5 7 6 9 11 10 8 
levOrder  : 8 6 10 5 7 9 11