二叉樹遞歸和非遞歸遍歷以及層次構建節點數爲n的二叉樹

目錄:

  1. 二叉樹深度
  2. 二叉樹前序遍歷
    1. 遞歸實現
    2. 二種非遞歸實現
  3. 二叉樹中序遍歷:
    1. 遞歸實現
    2. 非遞歸實現
  4. 二叉樹後序遍歷:
    1. 遞歸實現
    2. 非遞歸實現
  5. 二叉樹層次遍歷
  6. 二叉樹層次創建,創建方法遵循卡特蘭數



import java.util.Queue;

import java.util.Stack;

 

/*

 * ssuchange

 */

public class BinTreeTraversal {

    public static final int SIZE = 30;

    public static final char NULLNODE = '#';

    public static char[] Sequeuce =newchar[100];

    public static int SeqCount;

 

    static class Node {

        public Node(char ch) {

            val = ch;

            left = null;

            right = null;

        }

 

        char val;

        Node left;

        Node right;

    }

 

    public static void main(String[] args) {

        System.out.println("Start");

        // testTree();

        for (int i = 0; i < 26; i++)

            catalanCreateBinTree(i);

        System.out.println("End");

    }

 

    //         a

    //      /    \

    //     b      c

    //    / \    / \

    //   d  e   f   g

    //  /   /\     / \

    // h   i  j   k   l


    public static void testTree() {

        Node a = new Node('a');

        Node b = new Node('b');

        Node c = new Node('c');

        Node d = new Node('d');

        Node e = new Node('e');

        Node f = new Node('f');

        Node g = new Node('g');

        Node h = new Node('h');

        Node i = new Node('i');

        Node j = new Node('j');

        Node k = new Node('k');

        Node l = new Node('l');

        a.left = b;

        a.right = c;

        b.left = d;

        b.right = e;

        c.left = f;

        c.right = g;

        d.left = h;

        e.left = i;

        e.right = j;

        g.left = k;

        g.right = l;

        try {

            testTree(a);

        } catch (Exception e1) {

            e1.printStackTrace();

        }

    }

 

    public static void testTree(Node tree)throws Exception {

        String rightStr, computeStr;

        Println("****************");

        Println("Depth:\t" +depthRec(tree));

        Println("遞歸前序遍歷");

        SeqCount = 0;

        preTraRec(tree);

        rightStr = getSequence();

        Println();

        Println("非遞歸前序遍歷");

        Println("方法一");

        SeqCount = 0;

        preTraNoRec1(tree);

        computeStr = getSequence();

        if (!computeStr.equals(rightStr))

            throw new Exception("RightStr isnot equal computeStr!");

        Println();

        Println("方法二");

        SeqCount = 0;

        preTraNoRec2(tree);

        computeStr = getSequence();

        if (!computeStr.equals(rightStr))

            throw new Exception("RightStr isnot equal computeStr!");

        Println();

        Println("遞歸中序遍歷");

        SeqCount = 0;

        midTraRec(tree);

        rightStr = getSequence();

        Println();

        Println("非遞歸中序遍歷");

        SeqCount = 0;

        midTraNoRec(tree);

        computeStr = getSequence();

        if (!computeStr.equals(rightStr))

            throw new Exception("RightStr isnot equal computeStr!");

        Println();

        Println("遞歸後序遍歷");

        SeqCount = 0;

        postTraRec(tree);

        rightStr = getSequence();

        Println();

        Println("非遞歸後序遍歷");

        SeqCount = 0;

        postTraNoRec(tree);

        computeStr = getSequence();

        if (!computeStr.equals(rightStr))

            throw new Exception("RightStr isnot equal computeStr!");

        Println();

        Println("****************");

    }

 

    // 求二叉樹深度

    public static int depthRec(Node tree) {

        if (tree ==null)

            return 0;

        // 遞歸求解左右子樹深度。

        int leftDepth =depthRec(tree.left);

        int rightDepth =depthRec(tree.right);

        // 取左右子樹中大的加1作爲當前深度。

        return (leftDepth > rightDepth ? leftDepth: rightDepth) + 1;

    }

 

    // 訪問節點

    public static void visit(Node node) {

        if (node ==null)

            return;

        Print(node.val +" ");

        Sequeuce[SeqCount++] = node.val;

    }

 

    public static String getSequence() {

        return new String(Sequeuce, 0,SeqCount);

    }

 

    // 前序遍歷遞歸求解

    public static void preTraRec(Node tree) {

        if (tree ==null)

            return;

        visit(tree);

        preTraRec(tree.left);

        preTraRec(tree.right);

    }

 

    // 前序遍歷非遞歸求解

    // 先訪問當前節點,在不斷向下壓棧找左子樹,最後出棧訪問右子樹,此時,右子樹又成爲一顆單獨子樹

    public static void preTraNoRec1(Node tree) {

        if (tree ==null)

            return;

        Node node = tree;

        Node[] stack = new Node[SIZE];

        int top = 0;

        while (node !=null || top > 0) {

            while (node !=null) {

                // 訪問當前節點

                visit(node);

                // 記錄當前節點,用於查找當前節點的右子樹

                stack[top++] = node;

                // 訪問當前節點的左子樹

                node = node.left;

            }

            if (top > 0) {

                // 訪問完當前左子樹,出棧訪問右子樹

                node = stack[--top].right;

            }

        }

    }

 

    public static void preTraNoRec2(Node tree) {

        if (tree ==null)

            return;

        Node node = tree;

        Node[] stack = new Node[SIZE];

        int top = 0;

        stack[top++] = node;

        while (top > 0) {

            // 根節點出棧

            node = stack[--top];

            // 訪問根節點

            visit(node);

            // 因爲下一次出棧先訪問左子樹,所以先壓棧右子樹,再壓棧左子樹,使得左子樹先出棧

            // 右子樹節點壓棧

            if (node.right !=null)

                stack[top++] = node.right;

            // 左子樹節點壓棧

            if (node.left !=null)

                stack[top++] = node.left;

            // 根節點訪問完成後,將左右子樹壓棧,然後根節點丟棄。

        }

    }

 

    // 中序遍歷遞歸求解

    public static void midTraRec(Node tree) {

        if (tree ==null)

            return;

        midTraRec(tree.left);

        visit(tree);

        midTraRec(tree.right);

    }

 

    // 中序遍歷非遞歸求解

    // 與前序遍歷非遞歸求解相同,只要改變訪問節點的位置。

    public static void midTraNoRec(Node tree) {

        if (tree ==null)

            return;

        Node node = tree;

        Node[] stack = new Node[SIZE];

        int top = 0;

        while (node !=null || top > 0) {

            while (node !=null) {

                // 記錄當前節點,用於查找當前節點的右子樹

                stack[top++] = node;

                // 訪問當前節點的左子樹

                node = node.left;

            }

            if (top > 0) {

                // 訪問完當前左子樹,出棧訪問根節點

                node = stack[--top];

                // 訪問根節點

                visit(node);

                // 訪問右子樹

                node = node.right;

            }

        }

    }

 

    // 後序遍歷遞歸求解

    public static void postTraRec(Node tree) {

        if (tree ==null)

            return;

        postTraRec(tree.left);

        postTraRec(tree.right);

        visit(tree);

    }

 

    // 後序遍歷非遞歸求解

    public static void postTraNoRec(Node tree) {

        if (tree ==null)

            return;

        Node node = tree;

        Node[] stackCom = new Node[SIZE];

        int topCom = 0;

        Node[] stackVis = new Node[SIZE];

        int topVis = 0;

        stackCom[topCom++] = node;

        while (topCom > 0) {

            node = stackCom[--topCom];

            stackVis[topVis++] = node;

            if (node.left !=null)

                stackCom[topCom++] = node.left;

            if (node.right !=null)

                stackCom[topCom++] = node.right;

        }

        while (topVis > 0) {

            visit(stackVis[--topVis]);

        }

    }

 

    static class Queue<T> {

        Object[] queue = new Object[SIZE];

        int front = 0;

        int rear = 0;

 

        public void enqueue(T t) {

            if ((rear + 1) %SIZE ==front) {

                try {

                    thrownew Exception("Queue isfull!");

                } catch (Exception e) {

                    e.printStackTrace();

                }

            }

            queue[rear] = t;

            rear = (rear + 1) %SIZE;

        }

 

        public T dequeue() {

            if (rear ==front) {

                try {

                    thrownew Exception("Queue isempty!");

                } catch (Exception e) {

                    e.printStackTrace();

                }

            }

            T t = (T) queue[front];

            front = (front + 1) %SIZE;

            return t;

        }

 

        public boolean isEmpty() {

            returnrear ==front;

        }

    }

 

    // 層次遍歷

    public static void levelTra(Node tree) {

        if (tree ==null)

            return;

        Queue<Node> queue = newQueue<Node>();

        queue.enqueue(tree);

        while (!queue.isEmpty()) {

            Node node = queue.dequeue();

            visit(node);

            if (node.left !=null)

                queue.enqueue(node.left);

            if (node.right !=null)

                queue.enqueue(node.right);

        }

    }

 

    // 層次構建二叉樹

    public static Node levelCreate(char[] array) {

        if (array ==null || array.length == 0)

            return null;

        int index = 0;

        Node tree = null;

        if (array[index] ==NULLNODE)

            return tree;

        Queue<Node> queue = newQueue<Node>();

        tree = new Node(array[index]);

        index++;

        queue.enqueue(tree);

        while (!queue.isEmpty() && index <array.length) {

            Node node = queue.dequeue();

            if (array[index] ==NULLNODE)

                node.left = null;

            else {

                node.left = new Node(array[index]);

                queue.enqueue(node.left);

            }

            index++;

            if (array[index] ==NULLNODE)

                node.right = null;

            else {

                node.right = new Node(array[index]);

                queue.enqueue(node.right);

            }

            index++;

        }

        if (queue.isEmpty() && index == array.length)

            return tree;

        return null;

    }

 

    public static void testBinTree(char[] array) {

        // for (int i = 0; i < array.length; i++) {

        // Print(array[i]);

        // }

        // Println();

        Node tree = levelCreate(array);

        try {

            testTree(tree);

        } catch (Exception e) {

            e.printStackTrace();

        }

    }

 

    // 卡特蘭數構建二叉樹層次遍歷序列

    // 令二叉樹節點總數爲N,有另個孩子的節點數爲a,一個孩子的節點數爲b,沒有孩子的節點爲c

    // 2a+b+1=n,即除了根節點的所有節點都是其父節點的孩子節點,孩子節點加上根節點構成整個二叉樹;

    // a+b+c=n,即二叉樹節點由非葉子節點(雙孩子節點、單孩子節點)和葉子節點組成。

    // b+2c=n+1,即非空節點數爲n的二叉樹有n+1個空節點。

    // 非空節點數爲n的二叉樹滿足卡特蘭數的構建原則,推導見卡特蘭數百度百科。

    // 非空節點數爲n的二叉樹的層次遍歷序列共有2*n+1個數,最後一個一定爲空節點,前2*n個節點構建原則爲:

    // n1n0構成長度爲2*n的序列,任意位置前面和當前位置的1的個數一定大於等於0的個數,1代表非空節點,0代表空節點


//http://www.cppblog.com/MiYu/archive/2010/08/07/122573.html

    public static void catalanCreateBinTree(int n) {

        if (n <= 0 || n > 25)

            return;

        boolean[] arr =newboolean[2 * n];

        catalan(arr, 0, n);

    }


    // Catalan序列遞歸構造方法:

    // 如果當前位置前面的1的個數大於前面0的個數,當前位置可以填充1

    // 如果當前位置前面的1的個數小於n,當前位置可以填充1

    // 遞歸結束條件爲當前位置前面的1的個數等於n,則當前位置到序列結尾都填充0,構造結束。

    public static void catalan(boolean[] arr,int index,int trueLeft) {

        if (trueLeft == 0) {

            char[] array =newchar[arr.length + 1];

            char ch ='a';

            for (int i = 0; i < index; i++) {

                if (arr[i])

                    array[i] = ch++;

                else

                    array[i] = NULLNODE;

            }

            for(int i=index;i<array.length;i++)

                array[i] = NULLNODE;

            testBinTree(array);

        } else {

            arr[index] = true;

            catalan(arr, index + 1,trueLeft - 1);

            if (index + 1 <= arr.length - 2 * trueLeft) {

                arr[index] = false;

                catalan(arr, index + 1,trueLeft);

            }

        }

    }


    public static void Print(String str) {

        System.out.print(str);

    }

 

    public static void Println() {

        System.out.println();

    }

 

    public static void Println(String str) {

        Print(str);

        Println();

    }

}

 

參考鏈接:

http://blog.csdn.net/kofsky/article/details/2886453

下載地址:

http://download.csdn.net/detail/ssuchange/6730285

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