非遞歸遍歷二叉樹Java版的實現代碼(沒寫層次遍歷)

直接上代碼呵呵,裏面有註解java

 

package www.com.leetcode.specificProblem;

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


/**
 * 總結了三種非遞歸遍歷二叉樹
 * @author 85060
 *
 */
public class TraverseBinaryTree {

    
    //用來裝遍歷序列的一個list,展現的時候用
    private List<TreeNode> helpList = new ArrayList<>();
    
    public static void main(String[] args) {
        TreeNode root = createATree();
        TraverseBinaryTree traverseBinaryTree = new TraverseBinaryTree();
        
        
        //traverseBinaryTree.frontTraverseRecursion(root);
        //traverseBinaryTree.midTraverseRecursion(root);
        traverseBinaryTree.backTraverseRecursion(root);
        String rightAnswer = traverseBinaryTree.helpList.toString();
        System.out.println("right: " + rightAnswer);
        
        traverseBinaryTree.helpList.clear();
        
        //traverseBinaryTree.frontTravese(root);
        //traverseBinaryTree.midTraverse(root);
        traverseBinaryTree.backTraverse(root);
        String myAnswer = traverseBinaryTree.helpList.toString();
        System.out.println("my ans: " + myAnswer);
        System.out.println("bingo? " + rightAnswer.equals(myAnswer));
        
        
    }
    
    
    /**
     * 遞歸版的前序遍歷二叉樹
     * @param node
     */
    private void frontTraverseRecursion(TreeNode node) {
        if(node == null)return;
        helpList.add(node);
        frontTraverseRecursion(node.left);
        frontTraverseRecursion(node.right);
    }
    
    
    /**
     * 遞歸式的中序遞歸二叉樹
     * @param node
     */
    private void midTraverseRecursion(TreeNode node) {
        if(node == null)return;
        midTraverseRecursion(node.left);
        helpList.add(node);
        midTraverseRecursion(node.right);
    }
    
    
    /**
     * 遞歸式的後序遍歷二叉樹
     * @param node
     */
    private void backTraverseRecursion(TreeNode node) {
        if(node == null)return;
        backTraverseRecursion(node.left);
        backTraverseRecursion(node.right);
        helpList.add(node);
    }
    
    
    /**
     * 非遞歸的前序遍歷二叉樹
     * 用一個node,一直往左遍歷,一邊遍歷一邊入棧,當走到左邊的盡頭後,就出棧,而後去這個出棧元素的右子樹,繼續循環
     * @param root
     */
    private void frontTravese(TreeNode root) {
        if(root == null)return;
        Stack<TreeNode> stack = new Stack<TreeNode>();
        TreeNode node = root;
        
        while(node != null || !stack.isEmpty()) {
            if(node != null) {
                helpList.add(node);//visit
                stack.push(node);
                node = node.left;
            } else {
                //左子樹沒了,進入棧中而後去右子樹咯
                node = stack.pop().right;
            }
        }
    }
    
    /**
     * 非遞歸式的中序遞歸二叉樹
     * @param root
     */
    private void midTraverse(TreeNode root) {
        if(root == null)return ;
        
        Stack<TreeNode> stack = new Stack<TreeNode>();
        TreeNode node = root;
        
        while(node != null || !stack.isEmpty()) {
            
            while(node != null) {//一直往左走到盡頭
                stack.push(node);
                node = node.left;
            }
            if(!stack.isEmpty()) {
                node = stack.pop();
                helpList.add(node);//visit
                node = node.right;//進入右子樹
            }
        }
        
    }
    
    
    /**
     * 非遞歸的後序遍歷二叉樹
     * 後序遍歷的關鍵就是要判斷上一個結點的右孩子訪問了沒,因此要存上次訪問的結點
     * @param root
     */
    private void backTraverse(TreeNode root) {
        if(root == null)return;
        
        Stack<TreeNode> stack = new Stack<TreeNode>();
        TreeNode node = root;
        TreeNode lastVisit = null;//記錄剛剛訪問過的那個結點,用來區分stack中pop出來的結點的右子樹訪問過沒
        
        
        while(node != null || !stack.isEmpty()) {
            while(node != null) {//一直走到樹的最左邊,stack是最左邊的那個葉子結點
                stack.push(node);
                node = node.left;
            }
            
            while(!stack.isEmpty()) {
                node = stack.peek();
                if(node.right == null || node.right == lastVisit) {//沒有右子樹,右子樹訪問過了,均可以訪問這個結點了
                    helpList.add(node);//visit
                    //System.out.println(node);
                    lastVisit = node;
                    stack.pop();
                    if(stack.isEmpty())return;//這個很重要,否則會無限循環
                } else {//右子樹不爲空,並且沒訪問過
                    node = node.right;
                    break;//出去要走到這個右子樹的最左邊噢
                }
            }
        }
        
    }
    
    
    /**
     * 構造一顆測試用的二叉樹數據
     * @return
     */
    private static TreeNode createATree() {
        
        TreeNode root = new TreeNode(4);
        root.left = new TreeNode(3);
        root.right = new TreeNode(6);
        root.left.left = new TreeNode(11);
        root.left.right = new TreeNode(12);
        root.left.right.left = new TreeNode(45);
        root.right.left = new TreeNode(13);
        root.right.right = new TreeNode(14);
        root.right.right.right = new TreeNode(32);
        
        return root;
        
    }
}


/**
 * 二叉樹結點類
 * @author 85060
 *
 */
class TreeNode {
    int data;
    TreeNode left;
    TreeNode right;
    
    public TreeNode(int data) {
        this.data = data;
    }
    
    @Override
    public String toString() {
        // TODO Auto-generated method stub
        return data + "";
    }
}
相關文章
相關標籤/搜索