二叉樹的前序中序後序遍歷--遞歸和非遞歸兩種方式(Java實現)

 

 

簡單介紹一下:

前序遍歷:父節點--左孩子節點--右孩子節點

中序遍歷:左孩子節點--父節點--右孩子節點

後序遍歷:左孩子節點--右孩子節點--父節點

前中後指的是父節點在整個樹的處理過程中次序。

代碼:

實體類:

/**
 * @author yinglala
 */
public class BinaryTree {
    private int data;
    private BinaryTree lchild;
    private BinaryTree rchild;

    public BinaryTree(int data) {
        this.data = data;
    }


    public int getData() {
        return data;
    }

    public void setData(int data) {
        this.data = data;
    }

    public BinaryTree getLchild() {
        return lchild;
    }

    public void setLchild(BinaryTree lchild) {
        this.lchild = lchild;
    }

    public BinaryTree getRchild() {
        return rchild;
    }

    public void setRchild(BinaryTree rchild) {
        this.rchild = rchild;
    }
}

遍歷方法:



import java.util.Stack;

/**
 * @author yinglala
 */
public class BinaryTreeOrder {

    //前序遍歷
    private static void preOrder(BinaryTree t){
        if(t == null){
            return;
        }
        System.out.print(t.getData() + " ");
        preOrder(t.getLchild());
        preOrder(t.getRchild());
    }


    //中序遍歷
    private static void inOrder(BinaryTree t){
        if (t == null){
            return;
        }
        inOrder(t.getLchild());
        System.out.print(t.getData() + " ");
        inOrder(t.getRchild());
    }


    //後續遍歷
    private static void postOrder(BinaryTree t){
        if(t == null){
            return;
        }
        postOrder(t.getLchild());
        postOrder(t.getRchild());
        System.out.print(t.getData() + " ");
    }

    //非遞歸版本

    //非遞歸前序遍歷
    private static void nonRecursivePreOrder(BinaryTree t){
        if( t == null){
            return;
        }
        Stack<BinaryTree> stack = new Stack();
        stack.push(t);

        //棧不爲空 進行彈出等操作
        while (stack != null && stack.size() != 0){
            //彈出棧頂元素
            BinaryTree tmpTree = stack.pop();
            //打印
            System.out.print(tmpTree.getData() + " ");

            //若tmpTree同時存在左子樹和右子樹 先對右子樹進行壓棧 再對左子樹進行壓棧
            //根據棧的特性 左子樹位於棧頂 先彈出左子樹 再彈出右子樹
            if(tmpTree.getRchild() != null){
                stack.push(tmpTree.getRchild());
            }

            if(tmpTree.getLchild() != null){
                stack.push(tmpTree.getLchild());
            }
        }

    }

    //非遞歸版本中序遍歷
    private static void nonRecursiveInOrder(BinaryTree t){
        if(t == null){
            return;
        }
        Stack<BinaryTree> stack = new Stack();
        stack.push(t);
        //初始化輔助節點P
        BinaryTree p = t;
        while(stack != null && stack.size() != 0){
            //如果左孩子不爲空 先壓棧
            if(p != null && p.getLchild() != null){
                stack.push(p.getLchild());
                p = p.getLchild();
            }else {
                //彈出棧頂元素
                p = stack.pop();
                //打印
                System.out.print(p.getData() + " ");
                if(p.getRchild() != null){
                    stack.push(p.getRchild());
                    p = p.getRchild();
                }else {
                    //p = stack.pop(); p已經訪問過了 將p設置爲空
                    p = null;
                }

            }


        }
    }

    //非遞歸版本後序遍歷
    private static void nonRecursivePostOrder(BinaryTree t){
        if(t == null){
            return;
        }
        Stack<BinaryTree> stack = new Stack();
        stack.push(t);
        BinaryTree p = t;
        BinaryTree tVisit = null;
        while(stack != null && stack.size() != 0){
            //如果左孩子不爲空 先壓棧
            if(p != null && p.getLchild() != null){
                stack.push(p.getLchild());
                p = p.getLchild();
            }else{
                p = stack.peek();//獲取棧頂元素 並保證p不爲空

                //若沒有右孩子,或者右孩子已經被訪問過
                if(p.getRchild() == null || p.getRchild() == tVisit){
                    //打印
                    System.out.print(p.getData() + " ");
                    //標明上個被訪問的節點 防止在回溯的過程中無限訪問右孩子節點
                    tVisit = p;
                    p = null;
                    //棧頂元素及其孩子節點已訪問 出棧
                    stack.pop();
                }else{
                    stack.push(p.getRchild());
                    p = p.getRchild();
                }
            }


        }
    }

    public static void main(String[] args){
        BinaryTree root = new BinaryTree(1);
        BinaryTree second = new BinaryTree(2);
        BinaryTree three = new BinaryTree(3);
        BinaryTree four = new BinaryTree(4);
        BinaryTree five = new BinaryTree(5);
        BinaryTree six = new BinaryTree(6);
        BinaryTree seven = new BinaryTree(7);
        root.setLchild(second);
        root.setRchild(three);
        second.setLchild(four);
        second.setRchild(five);
        three.setLchild(six);
        three.setRchild(seven);

        System.out.println("遞歸先序遍歷:");
        preOrder(root);
        System.out.println();
        System.out.println("遞歸中序遍歷:");
        inOrder(root);
        System.out.println();
        System.out.println("遞歸後序遍歷:");
        postOrder(root);
        System.out.println();
        System.out.println("非遞歸先序遍歷:");
        nonRecursivePreOrder(root);
        System.out.println();
        System.out.println("非遞歸中序遍歷:");
        nonRecursiveInOrder(root);
        System.out.println();
        System.out.println("非遞歸後序遍歷:");
        nonRecursivePostOrder(root);

    }


}

執行結果:

遞歸先序遍歷:
1 2 4 5 3 6 7 
遞歸中序遍歷:
4 2 5 1 6 3 7 
遞歸後序遍歷:
4 5 2 6 7 3 1 
非遞歸先序遍歷:
1 2 4 5 3 6 7 
非遞歸中序遍歷:
4 2 5 1 6 3 7 
非遞歸後序遍歷:
4 5 2 6 7 3 1 
Process finished with exit code 0

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章