自学内容网 自学内容网

二叉树---java---黑马

二叉树

遍历

遍历分两种

广度优先遍历

尽可能先访问距离根节点最近的节点,也称之为层序遍历。
在这里插入图片描述

深度优先遍历

对于二叉树,进一步分为三种

  1. pre-order前序遍历,对于每一颗子树,先访问该节点,然后是左子树,最后是右子树;
  2. in-order中序遍历,对于每一颗子树,先访问左子树,然后是该节点,最后是右子树;
  3. post-order后序遍历,对于每一颗子树,先访问左子树,然后是右子树,最后是该节点;
使用递归方式实现
前序遍历
public class TreeNode{
    TreeNode left;
    int value;
    TreeNode right;
    
    public TreeNode() {
        
    }
    
    public TreeNode(TreeNode left, int value, TreeNode) {
        this.left = left;
        this.value = value;
        this.right = right;
    }
    
    @Override
    public String toString() {
        return String.valueOf(this.value);
    }
}
public class TreeTraversal{
    
    public static void main(String[] args) {
        TreeNode root = new TreeNode(
            new TreeNode(new TreeNode(4, 2, null)), 
            1, 
            new TreeNode(new TreeNode(5, 3, new TreeNode(6))));
    }
    
    public void preOrder(TreeNode node) {
        if (node == null) {
            return;
        }
        System.out.println(node.value + "\t");// 值
        preOrder(node.left);// 左
        preOrder(node.right);// 右
    }
    
    public void inOrder(TreeNode node) {
        if (node == null) {
            return;
        }
        preOrder(node.left);// 左
        System.out.println(node.value + "\t");// 值
        preOrder(node.right);// 右
    }
    
    public void postOrder(TreeNode node) {
        if (node == null) {
            return;
        }
        preOrder(node.left);// 左
        preOrder(node.right);// 右
        System.out.println(node.value + "\t");// 值
    }
    
}
非递归实现
前序遍历和中序遍历
public class TreeTraversal{
    
    public static void main(String[] args) {
        TreeNode root = new TreeNode(
            new TreeNode(new TreeNode(4, 2, null)), 
            1, 
            new TreeNode(new TreeNode(5, 3, new TreeNode(6))));
        Stack<Integer> stack = new Stack<>();
        TreeNode curr = root;
        while (curr != null || !stack.isEmpty()) {
            if (curr != null) {
                System.out.println(curr.value);// 前序遍历
                stack.push(curr);
                curr = curr.left;
            } else {
                TreeNode pop = stack.pop();
                System.out.println(pop.value);// 中序遍历
                curr = pop.right;
            }
        }
    }
}
后序遍历
public class TreeTraversal{
    
    public static void main(String[] args) {
        TreeNode root = new TreeNode(
            new TreeNode(new TreeNode(4, 2, null)), 
            1, 
            new TreeNode(new TreeNode(5, 3, new TreeNode(6))));
        Stack<Integer> stack = new Stack<>();
        TreeNode curr = root;
        TreeNode pop = null;
        while (curr != null || !stack.isEmpty()) {
            if (curr != null) {
                stack.push(curr);
                curr = curr.left;
            } else {
                TreeNode peek = stack.peek();
                if (peek.right == null || peek.right == peek) {
                    pop = stack.pop();
                    System.out.println(pop.value);// 后序遍历
                } else {
                    curr = peek.right;
                }
            }
        }
    }
}
同时实现前序遍历、中序遍历和后序遍历
public class TreeTraversal{
    
    public static void main(String[] args) {
        TreeNode root = new TreeNode(
            new TreeNode(new TreeNode(4, 2, null)), 
            1, 
            new TreeNode(new TreeNode(5, 3, new TreeNode(6))));
        Stack<Integer> stack = new Stack<>();
        TreeNode curr = root;// 当前节点
        TreeNode pop = null;// 最近一次弹栈节点
        while (curr != null || !stack.isEmpty()) {
            if (curr != null) {
                stack.push(curr);
                // 待处理左子树
                System.out.println(curr.value);// 前序遍历
                curr = curr.left;
            } else {
                TreeNode peek = stack.peek();
                // 无右子树
                if (peek.right == null) {
                    System.out.println(peek.value);// 中序遍历
                    pop = stack.pop();
                    System.out.println(pop.value);// 后序遍历
                } 
                // 右子树处理完成
                else if (peek.right == peek) {
                    pop = stack.pop();
                    System.out.println(pop.value);// 后序遍历
                } 
                // 待处理右子树
                else {
                    System.out.println(peek.value);// 中序遍历
                    curr = peek.right;
                }
            }
        }
    }
}

Leetcode

Leetcode101对称二叉树

public class Leetcode101{
    
    public boolean isSymmetric(TreeNode root) {
        return check(root.left, root.right);
    }
    
    public boolean check(TreeNode left, TreeNode right) {
        if (left == null && right == null) {
            return true;
        }
        if (right == null || left == null) {
            return false;
        }
        if (left.value != right.value) {
            return false;
        }
        return check(left.left, right.right) && check(left.right, right.left);
    }
}

Leetcode104最大深度

方法一

使用递归

public class Leetcode104{
    
   public int maxDepth(TreeNode root) {
        if (root == null) {
            return 0;
        }
        if (root.left == null && root.right == null) {
            return 1;
        }
        int i = maxDepth(root.left);
        int j = maxDepth(root.right);
        return Math.max(i, j) + 1;
    }
}
方法二

使用后序遍历

public class Leetcode104{
    
   public int maxDepth(TreeNode root) {
        TreeNode curr = root;
        Stack<TreeNode> stack = new Stack<>();
        TreeNode pop = null;// 最近一次弹栈元素/节点
        int max = 0;// 栈的最大深度
        while(curr != null || !stack.isEmpty()) {
            if (curr != null) {
                stack.push(curr);
                if (stack.size() > max) {
                    max = stack.size();
                }
                curr = curr.next;
            } else {
                TreeNode peek = stack.peek();
                if (peek.right == null || peek.right == pop) {
                    pop = stack.pop();
                } else {
                    curr = peek.right;
                }
            }
        }
    }
}
方法三

使用层序遍历

public class Leetcode104{
    
   public int maxDepth(TreeNode root) {
        if (root == null) {
            return 0;
        }
        LinkedList<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        int depth = 0;
        while(!queue.isEmpty()) {
            int size = queue.size();// 写在循环内,需要多次调用,所以写在循环外
            for(int i = 0; i < size; i++) {
                TreeNode poll = queue.poll();
                if (poll.left != null) {
                    queue.offer(poll.left);
                }
                if (poll.right != null) {
                    queue.offer(poll.right);
                }
            }
            depth++;
        }
        return depth;
    }
}

Leetcode111二叉树最小深度

方法一
public class Leetcode111{
    
    public int minDepth(TreeNode root) {
        if (root == null) {
            return 0;
        }
        int d1 = minDepth(root.left);
        int d2 = minDepth(root.right);
        if (d1 == 0) {// 当左子树为空
            return d2 + 1;
        } 
        if (d2 == 0) {// 当右子树为空
            return d1 + 1;
        }
        return Math.min(d1, d2) + 1;
    }
}
方法二

使用层序遍历实现,找到第一个叶子节点,求得最小深度

public class Leetcode111{
    
    public int minDepth(TreeNode root) {
        if (root == null) {
            return 0;
        }
        LinkedList<TreeNode> queue = new LinkedList<>();// LinkedList可以作为双向链表、队列、栈
        queue.offer(root);
        int c1 = 1;
        int depth = 0;
        while (!queue.isEmpty()) {
            int c2 = 0;
            depth++;
            for(int i = 0; i < c1; i++) {
                TreeNode poll = queue.poll();
                if (poll.left == null && poll.right == null) {
                    return depth;
                }
                if (poll.left != null) {
                    queue.offer(poll.left);
                    c2++;
                }
                if (poll.right != null) {
                    queue.offer(poll.right);
                    c2++;
                }
            }
            c1 = c2;
        }
        return depth;
    }
}

Leetcode226

二叉树反转

public class Leetcode226{
    public TreeNode invertTree(TreeNode root) {
        if (root == null ||(root.left == null && root.right == null)) {
            return root;
        }
        fn(root);
        return root;
    }
    
    public void fn(TreeNode node) {
        if (node == null) {
            return;
        }
        TreeNode temp = node.left;
        node.left = node.right;
        node.right = temp;
        fn(node.left);
        fn(node.right);
    }
}

后缀表达式构建二叉树

中缀表达式(2 - 1) * 3
后缀表达式/逆波兰表达式21-3*
    
    表达树
    *
   / \
  -   3
 / \
2   1 
public class ExpressionTree{
    
    public TreeNode constructExpressionTree (String[] tokens){
        Stack<TreeNode> stack = new Stack<>();
        for(String t : tokens) {
            switch (t) {
                case "+", "-", "*", "/" -> {// 运算符
                    TreeNode right = stack.pop();
                    TreeNode left = stack.pop();
                    TreeNode parent = new TreeNode(t);
                    parent.left = left;
                    parent.right = right;
                    stack.push(parent);
                }
                default -> {// 数字
                    stack.push(new TreeNode(t));
                }    
            }
        }
        return stack.peek();
    }
}

Leetcode105

根据前序遍历和中序遍历,得到二叉树

public class Leetcode105{
    public TreeNode buildTree(int[] preOrder, int inOrder) {
        if (preOrder.length == 0) {
            return null;
        }
        // 创建根节点
        int rootValue = preOrder[0];
        TreeNode root = new TreeNode(rootValue);
        for(int i = 0; i < inOrder.length; i++) {
            if (inOrder[i] == rootValue) {
                int[] inLeft = Arrays.copyOfRange(inOrder, 0, i);
                int[] inRight = Arrays.copyOfRange(inOrder, i + 1, inOrder.length);
                
                int[] preLeft = preLeftArrays.copyOfRange(preOrder, 1, i + 1);
                int[] preRight = Arrays.copyOfRange(preOrder, i + 1, preOrder.length);
                
                root.left = buildTree(preLeft, inLeft);
                root.right = buildTree(preRight, inRight);
                break;
            }
        }
        return root;
    }
}

Leetcode106

根据中序遍历和后序遍历得到二叉树

public class Leetcode106{
    public TreeNode buildTree(int[] inOrder, int postOrder) {
        if (postOrder.length == 0) {
            return null;
        }
        // 创建根节点
        int rootValue = postOrder[postOrder.length - 1];
        TreeNode root = new TreeNode(rootValue);
        for(int i = 0; i < inOrder.length; i++) {
            if (inOrder[i] == rootValue) {
                int[] inLeft = Arrays.copyOfRange(inOrder, 0, i);
                int[] inRight = Arrays.copyOfRange(inOrder, i + 1, inOrder.length);
                
                int[] postLeft = preLeftArrays.copyOfRange(preOrder, 0, i);
                int[] postRight = Arrays.copyOfRange(preOrder, i, preOrder.length - 1);
                
                root.left = buildTree(inLef, tpostLeft);
                root.right = buildTree(inRight, postRight);
                break;
            }
        }
        return root;
    }
}
            int[] inRight = Arrays.copyOfRange(inOrder, i + 1, inOrder.length);
            
            int[] postLeft = preLeftArrays.copyOfRange(preOrder, 0, i);
            int[] postRight = Arrays.copyOfRange(preOrder, i, preOrder.length - 1);
            
            root.left = buildTree(inLef, tpostLeft);
            root.right = buildTree(inRight, postRight);
            break;
        }
    }
    return root;
}

}


原文地址:https://blog.csdn.net/weixin_49326024/article/details/142433016

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!