zoukankan      html  css  js  c++  java
  • 二叉树的遍历

    前序遍历

    非递归

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

    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;
        }
    }
    
  • 相关阅读:
    LVS + Keepalived + Nginx基于DR模式构建高可用方案
    基于SpringBoot从零构建博客网站
    基于SpringBoot从零构建博客网站
    基于SpringBoot从零构建博客网站
    基于SpringBoot从零构建博客网站
    精通Java中的volatile关键字
    基于Mycat实现读写分离
    整体二分
    pb_ds模板
    树状数组上二分(logn求第k小)
  • 原文地址:https://www.cnblogs.com/wunsiang/p/12713970.html
Copyright © 2011-2022 走看看