二叉树学习总结

这几天刷的算法题都是二叉树相关的,这里就放一点二叉树的知识:

首先是遍历:

前序遍历:根结点 ---> 左子树 ---> 右子树

中序遍历:左子树---> 根结点 ---> 右子树

后序遍历:左子树 ---> 右子树 ---> 根结点

层次遍历:一层一层输出

1.前序遍历:根左右

递归

 public void inorder(TreeNode root) {
        if (root == null) {
            return;
        }
        System.out.println(root.val);
        inorder(root.left, res);
        inorder(root.right, res);
    }

 

非递归:

 如果采用非递归的实现,顺序不变依然是根然后左右,因为是先左之后还要找到根的右孩子,所以要保存根节点,采用栈进行保存。

从最开始的根节点开始,

1。如果不是空,那么输出该根节点数据同时将该节点入栈,并将其左孩子节点定为目标节点

2。然后再判断当前节点是否为空,如果是空则出栈,将出栈的结点的右孩子节点定位目标节点,否则重复第一步直到栈空且结点为空

public void preOrderTraverse2(TreeNode root) {  
        LinkedList<TreeNode> stack = new LinkedList<>();  
        TreeNode pNode = root;  
        while (pNode != null || !stack.isEmpty()) {  
            if (pNode != null) {  
                System.out.print(pNode.val+"  ");  
                stack.push(pNode);  
                pNode = pNode.left;  
            } else { //pNode == null && !stack.isEmpty()  
                TreeNode node = stack.pop();  
                pNode = node.right;  
            }  
        }  
    }  

 

2.中序遍历:左根右

递归

 public void inorder(TreeNode root) {
        if (root == null) {
            return;
        }
        System.out.println(root.val);
        inorder(root.left, res);
        inorder(root.right, res);
    }

非递归:

 和前序遍历相似,只是将输出根节点的时刻放到右孩子之前

public void preOrderTraverse2(TreeNode root) {  
        LinkedList<TreeNode> stack = new LinkedList<>();  
        TreeNode pNode = root;  
        while (pNode != null || !stack.isEmpty()) {  
            if (pNode != null) {  
                stack.push(pNode);  
                pNode = pNode.left;  
            } else { //pNode == null && !stack.isEmpty()  
                TreeNode node = stack.pop();  
                System.out.print(node.val+"  ");  
                pNode = node.right;  
            }  
        }  
    }

 

3.后序遍历:左右根

递归

public void inorder(TreeNode root) {
        if (root == null) {
            return;
        }
        inorder(root.left, res);
        inorder(root.right, res);
        System.out.println(root.val);
    }

非递归

 后序遍历的非递归是最难的,要保证左右全部访问之后再重新回到根节点,

不太好写,等以后搞明白了再来吧

4.层次遍历:

比较简单,用队列保存结点就可以,需要注意的是,一定要注意root为空或者左右孩子为空的情况

class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        if(root==null){
            return new ArrayList<>();
        }
       Queue<TreeNode> queue=new LinkedList<>();
       List<List<Integer>> res=new ArrayList<>();
       queue.add(root);
       while(!queue.isEmpty()){
           int len=queue.size();
            List<Integer> r=new ArrayList<>();
           for(int i=0;i<len;i++){
            TreeNode node=queue.poll();
             r.add(node.val);
             if(node.left!=null)
             queue.add(node.left);
             if(node.right!=null)
             queue.add(node.right);
           }
           res.add(r);
       }
       return res;
    }
}

 5.二叉树左右孩子交换

层次:

class Solution {
    public TreeNode invertTree(TreeNode root) {
        if(root==null){
            return root;
        }
    Queue<TreeNode> queue=new LinkedList<>();
    TreeNode res=root;
    queue.add(root);
    while(!queue.isEmpty()){
        int len=queue.size();
        for(int i=0;i<len;i++){
            TreeNode node=queue.poll();
            if(node.left!=null){queue.add(node.left);}
            if(node.right!=null){queue.add(node.right);}
            TreeNode childnode=node.left;
            node.left=node.right;
            node.right=childnode;
        }
    }
    return res;
    }
}

先序:

class Solution {
        // 先序遍历--从顶向下交换
        public TreeNode invertTree(TreeNode root) {
            if (root == null) return null;
            // 保存右子树
            TreeNode rightTree = root.right;
            // 交换左右子树的位置
            root.right = invertTree(root.left);
            root.left = invertTree(rightTree);
            return root;
        }
    }

 

posted @ 2020-09-14 19:59  PPGwo  阅读(306)  评论(0)    收藏  举报