二叉树的遍历

前序遍历

非递归

从根节点开始,每次迭代弹出当前栈顶元素访问,并将其孩子节点压入栈中,先压右孩子再压左孩子(入栈是逆序的,从而出栈为先左后右,再加上最开始的根节点,就是根左右)。

public List<Integer> preorderTraversal(TreeNode root) {
    List<Integer> res = new ArrayList<Integer>();
    if(root == null)
        return res;
    Stack<TreeNode> st = new Stack<TreeNode>();
    st.push(root);
    while(!st.isEmpty()){
        TreeNode c = st.pop();
        res.add(c.val);
        if(c.right != null){
            st.push(c.right);
        }
        if(c.left != null){
            st.push(c.left);
        }
    }
    return res;
}

中序遍历

非递归

1、若当前节点不为空,则压栈,然后向左子节点走2、当前节点为空,则出栈,访问,然后想这个节点的右子节点走


public static void inOrderUnRecur(Node head) {
		System.out.print("in-order: ");
		if (head != null) {
			Stack<Node> stack = new Stack<Node>();
			while (!stack.isEmpty() || head != null) {
				if (head != null) {
					stack.push(head);
					head = head.left;
				} else {
					head = stack.pop();
					System.out.print(head.value + " ");
					head = head.right;
				}
			}
		}
		System.out.println();
	}


后序遍历

非递归

方法1

由于后续是“左右根”,后前序为“根左右”,那只需要把前序改成“根右左”,再将结果置逆就得到了“左右根”,然后返回即可。

public List<Integer> postorderTraversal(TreeNode root) {
        List<Integer> res = new ArrayList<>();
        if(root == null)
            return res;
        Stack<TreeNode> st = new Stack<>();
        st.push(root);
        while (!st.isEmpty()){
            TreeNode c = st.pop();
            res.add(c.val);//与前序唯一区别就是子节点压栈次序改变
            if(c.left != null){
                st.push(c.left);
            }
            if(c.right != null){
                st.push(c.right);
            }
        }
        Collections.reverse(res);
        return res;
    }

方法2

有一个last节点,记录右子树是否被访问过,整体思路和中序遍历比较像,先一直往左走,不断入栈,再判断最后一个节点,是否有右子树,或者右子树是否已经被访问过,关键在于这个last节点,用于判断右字数是否已被访问。

class Solution {
    public List<Integer> postorderTraversal(TreeNode root) {
        List<Integer> res = new ArrayList<Integer>();
        if(root == null){
            return res;
        }
        Stack<TreeNode> st = new Stack<>();
        TreeNode c = root,last = null;
        while(c != null || !st.isEmpty()){
            while(c != null){
                st.push(c);
                c = c.left;
            }
            c = st.peek();
            if(c.right == null || c.right == last){
                last = st.pop();
                res.add(c.val);
                c = null;
            }else{
                c = c.right;
            }
        }
        return res;
    }
}

二叉树的层次遍历

leetcode 面试题32 - I. 从上到下打印二叉树

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public int[] levelOrder(TreeNode root) {
        List<Integer> res = new ArrayList<>();
        Queue<TreeNode> queue = new LinkedList<>();
        if(root != null){
            queue.add(root);
        }
        while(!queue.isEmpty()){
            TreeNode node = queue.poll();
            res.add(node.val);
            if(node.left != null)
                queue.offer(node.left);
            if(node.right != null)
                queue.offer(node.right);
        }
        int[] arr = new int[res.size()];
        for(int i=0; i<res.size(); i++) {
            arr[i] = res.get(i);
        }
        return arr;
    }
}


从前序与中序遍历序列构造二叉树

Leetcode105

递归解法

关键在于找到每个子树的边界

class Solution {
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        if(preorder == null || preorder.length == 0)
            return null;
        map = new HashMap<>();//优化查找速度
        for(int i = 0;i < preorder.length;i++){
            map.put(inorder[i],i);
        }
        return generate(preorder,0,preorder.length - 1,inorder,0,inorder.length - 1);
    }
    HashMap<Integer,Integer> map;
    public TreeNode generate(int[] preorder,int preStart,int preEnd, int[] inorder,int inStart,int inEnd){
        if(preStart > preEnd || inStart > inEnd)
            return null;
        TreeNode c = new TreeNode(preorder[preStart]);
        int inIndex = map.get(c.val);
        c.left = generate(preorder,preStart + 1,preStart + inIndex - inStart,inorder,inStart,inIndex - 1);
        c.right = generate(preorder,preStart + inIndex - inStart + 1,preEnd,inorder,inIndex + 1,inEnd);
        return c;
    }
}
posted @ 2019-06-15 22:57  wunsiang  阅读(123)  评论(0编辑  收藏  举报