二叉樹的遍歷

import java.util.ArrayList; import java.util.Stack;java

/**
 * 先序遍歷:按照「根左右」的順序,先遍歷根節點,再遍歷左子樹,再遍歷右子樹
 * 中序遍歷:按照「左根右「的順序,先遍歷左子樹,再遍歷根節點,最後遍歷右子樹
 * 後續遍歷:按照「左右根」的順序,先遍歷左子樹,再遍歷右子樹,最後遍歷根節點
 * <p>
 * 說明:
 *		1)這裏的'先/中/後'是指每次遍歷的時候,根節點被遍歷的順序。
 * 		2)每一個節點均可以看作一個跟節點。
 * 		3)遍歷的時候,咱們會將當前節點做爲一個根節點來看待。
 */

public class BinaryTree {

Integer value;
BinaryTree leftChild;
BinaryTree rightChild;

public BinaryTree(Integer value, BinaryTree leftChild, BinaryTree rightChild) {
    this.value = value;
    this.leftChild = leftChild;
    this.rightChild = rightChild;
}


// 存放遍歷後的節點
static ArrayList<BinaryTree> list = new ArrayList<BinaryTree>();

/**
 * 先序遍歷
 */
public static void preOrder(BinaryTree root) {

    if (root == null) return;

    list.add(root);                 // 1.將當前節點(根節點)存入list
    if (root.leftChild != null) {   // 2.當前節點的左子樹不爲空時,繼續往左找
        preOrder(root.leftChild);
    }                               // 3.當前節點的左子樹爲空時,說明根節點和左孩子已經遍歷完畢了,則接下來遍歷右孩子

    if (root.rightChild != null) {
        preOrder(root.rightChild);
    }
}

/**
 * 中序遍歷
 */
public static void inOrder(BinaryTree root) {

    if (root == null) return;

    if (root.leftChild != null) {
        inOrder(root.leftChild);
    }
    list.add(root);
    if (root.rightChild != null) {
        inOrder(root.rightChild);
    }
}

/**
 * 後序遍歷
 */
public static void postOrder(BinaryTree root) {

    if (root == null) return;

    if (root.leftChild != null) {
        postOrder(root.leftChild);
    }
    if (root.rightChild != null) {
        postOrder(root.rightChild);
    }
    list.add(root);

}


/**
 * 先序遍歷 非遞歸
 *
 * [@param](https://my.oschina.net/u/2303379) root
 */
public static void preOrderNonRecursion(BinaryTree root) {

    if (root == null) return;

    Stack<BinaryTree> stack = new Stack<BinaryTree>();

    BinaryTree currentNode = root;

    while (!stack.empty() || currentNode != null) {

        while (currentNode != null) {
            list.add(currentNode);
            stack.push(currentNode);                // 1.將當前節點(根節點)存在棧中
            currentNode = currentNode.leftChild;    // 2.當前節點的左子樹不爲空時,將當前節點的左子樹做爲根節點,繼續執行循環。 注:這裏與遞歸式的先序遍歷相似。
        }                                           // 3.當前節點的左子樹爲空時,說明根節點和左孩子已經遍歷完畢了,則接下來遍歷右孩子

        if (!stack.empty()) {
            currentNode = stack.pop();
            currentNode = currentNode.rightChild;
        }

    }
}

/**
 * 中序遍歷 非遞歸
 *
 * [@param](https://my.oschina.net/u/2303379) root
 */
public static void inOrderNonRecursion(BinaryTree root) {

    if (root == null) return;

    Stack<BinaryTree> stack = new Stack<BinaryTree>();

    BinaryTree currentNode = root;

    while (!stack.empty() || currentNode != null) {

        while (currentNode != null) {
            stack.push(currentNode);
            currentNode = currentNode.leftChild;
        }

        // 當root爲空時,說明已經到達左子樹最下邊,這時須要出棧了
        if (!stack.empty()) {
            currentNode = stack.pop();
            list.add(currentNode);
            currentNode = currentNode.rightChild;
        }

    }
}

/**
 * 後序遍歷 非遞歸
 *  要點:
 *      1)後序遍歷須要判斷上次訪問的節點是位於左子樹,仍是右子樹。
 *      2)  如果位於左子樹,則需跳過根節點,先進入右子樹,再回頭訪問根節點;
 *      3)  如果位於右子樹,則直接訪問根節點。
 *
 * [@param](https://my.oschina.net/u/2303379) root
 */
public static void postOrderNonRecursion(BinaryTree root) {

    if (root == null) return;

    Stack<BinaryTree> stack = new Stack<BinaryTree>();

    BinaryTree currentNode = root;   // 當前訪問的節點
    BinaryTree lastVisitNode = null; // 上次訪問的節點

    // 把currentNode移到當前節點的左子樹的最左邊
    while (currentNode != null) {
        stack.push(currentNode);
        currentNode = currentNode.leftChild;
    }

    while (!stack.empty()) {
        currentNode = stack.pop();

        // 後續遍歷中,一個根節點被訪問的前提是:當前節點(能夠當作根節點)無右子樹 或 當前節點的右子樹剛剛被訪問過。
        if (currentNode.rightChild != null && currentNode.rightChild != lastVisitNode) {

            stack.push(currentNode); // 當前節點的右子樹不爲空且沒有被訪問過,故根節點(當前節點)再次入棧。

            // 進入右子樹,把currentNode移到當前節點的右子樹的最左邊
            currentNode = currentNode.rightChild;
            while (currentNode != null) {
                stack.push(currentNode);
                currentNode = currentNode.leftChild;
            }
        } else {
            // 訪問
            list.add(currentNode);
            lastVisitNode = currentNode;
        }
    }

}


/**
 * 返回當前數的深度
 * 1.若是一棵樹只有一個結點,它的深度爲1
 * 2.若是根結點只有左子樹而沒有右子樹,那麼樹的深度是其左子樹的深度加1
 * 3.若是根結點只有右子樹而沒有左子樹,那麼樹的深度應該是其右子樹的深度加1
 * 4.若是既有右子樹又有左子樹,那該樹的深度就是其左、右子樹深度的較大值加1
 *
 * [@param](https://my.oschina.net/u/2303379) root
 * [@return](https://my.oschina.net/u/556800)
 */
public static int getTreeDepth(BinaryTree root) {
    int left = 0, right = 0;

    if (root.leftChild == null && root.rightChild == null) {
        return 1;
    }
    if (root.leftChild != null) {
        left = getTreeDepth(root.leftChild);
    }
    if (root.rightChild != null) {
        right = getTreeDepth(root.rightChild);
    }
    return left > right ? left + 1 : right + 1;
}

/**
 * 樹的初始化:先從葉子節點開始,由葉到根
 */
public static BinaryTree getBinaryTree() {

    BinaryTree leaf1 = new BinaryTree(11, null, null);
    BinaryTree leaf2 = new BinaryTree(12, null, null);
    BinaryTree firstMidNode1 = new BinaryTree(21, leaf1, leaf2);

    BinaryTree leaf3 = new BinaryTree(13, null, null);
    BinaryTree leaf4 = new BinaryTree(14, null, null);
    BinaryTree firstMidNode2 = new BinaryTree(22, leaf3, leaf4);

    BinaryTree secondMidNode1 = new BinaryTree(31, firstMidNode1, firstMidNode2);
    BinaryTree leaf5 = new BinaryTree(32, null, null);

    BinaryTree root = new BinaryTree(41, secondMidNode1, leaf5);
    return root;
}

public static void main(String[] args) {

    BinaryTree root = getBinaryTree();
//        preOrder(root);
//        inOrder(root);
//        postOrder(root);
           preOrderNonRecursion(root);
//        inOrderNonRecursion(root);
//        postOrderNonRecursion(root);

    ArrayList<Integer> resultList = new ArrayList<Integer>();
    for (BinaryTree node : list) {
        resultList.add(node.value);
    }
    System.out.println("遍歷的結果:" + resultList);
    System.out.println("樹的高度:" + getTreeDepth(root));

}

}node

相關文章
相關標籤/搜索