代码随想录刷题记录day13 之二叉树的遍历(递归+迭代)

代码随想录刷题记录day13 之二叉树的遍历(递归+迭代)

二叉树基础

分类

  • 满 二叉树

如果一棵二叉树只有度为0的结点和度为2的结点,并且度为0的结点在同一层上,则这棵二叉树为满二叉树。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PVDQWBSB-1667919759460)(代码随想录刷题.assets/image-20221108155237929.png)]

  • 完全二叉树

在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层,则该层包含 1~ 2^(h-1) 个节点。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HWf3QNFU-1667919759462)(代码随想录刷题.assets/image-20221108155342075.png)]

  • 二叉搜索树

    有数值的数,

    • 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
    • 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
    • 它的左、右子树也分别为二叉排序树

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GMqAAKPk-1667919759462)(代码随想录刷题.assets/image-20221108155615428.png)]

  • 平衡二叉搜索树

    在二叉搜索树的基础上,左右的高度差不超过1

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iqYyMGr6-1667919759463)(代码随想录刷题.assets/image-20221108160216603.png)]

二叉树存储方式

链式和顺序存储

  • 链式

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7GleA4af-1667919759463)(代码随想录刷题.assets/image-20221108160340974.png)]

  • 顺序

在数组中的存储规则:

父节点的下标为i,左孩子就是i*2+1,右孩子就是i*2+2。

二叉树的定义


递归遍历

leetcode:144. 二叉树的前序遍历

递归三部曲:

1.确定递归的终止条件

2.确定函数的参数和返回值

3.单层递归的逻辑

前序的顺序是中左右

下图模拟递归的执行流程

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5uZpxH4V-1667919759464)(代码随想录刷题.assets/image-20221108171054339.png)]

代码
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public List<Integer> preorderTraversal(TreeNode root) {
        //递归三部曲 
        //1.确定递归终止条件
        //2.确定递归的返回值
        //3.单层内的递归逻辑
        List<Integer> res=new ArrayList<>();
        if(root==null) return res;

        helper(root,res);

        return res;
    }

    public void helper(TreeNode node,List<Integer> res){
        if(node==null) return;
        res.add(node.val);
        if(node.left!=null) helper(node.left,res);
        if(node.right!=null) helper(node.right,res); 
    }
}
leetcode:145. 二叉树的后序遍历

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ychmsXWq-1667919759464)(代码随想录刷题.assets/image-20221108172502212.png)]

代码
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public List<Integer> postorderTraversal(TreeNode root) {
        List<Integer> res=new ArrayList<>();
        if(root==null) return res;

        helper(root,res);

        return res;

    }
    public void helper(TreeNode node,List<Integer> res){
        if(node==null) return;
        
        if(node.left!=null) helper(node.left,res);
        if(node.right!=null) helper(node.right,res); 
        res.add(node.val);
    }
}
leetcode:94. 二叉树的中序遍历

遍历示意图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3Qb7BbkZ-1667919759465)(代码随想录刷题.assets/image-20221108172310462.png)]

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> res=new ArrayList<>();
        if(root==null) return res;

        helper(root,res);

        return res;

    }
    public void helper(TreeNode node,List<Integer> res){
        if(node==null) return;
        
        if(node.left!=null) helper(node.left,res);
        res.add(node.val);
        if(node.right!=null) helper(node.right,res); 
        
    }
}

迭代法

前序遍历 leetcode144题

用一个栈来实现,前序遍历 入栈的顺序是先右节点,再左节点,这样子出栈的顺序才变成先左节点,再右节点。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2hrNRDSn-1667919759465)(代码随想录刷题.assets/image-20221108212424838.png)]

代码
public List<Integer> preorderTraversal(TreeNode root) {
        //通过栈的形式来实现
        List<Integer> res=new ArrayList<>();
        if(root==null) return res;

        Stack<TreeNode> stack=new Stack<>();
    
        stack.push(root);

        while (!stack.isEmpty()){
            TreeNode node=stack.peek();//第一个节点弹出
            stack.pop();
            res.add(node.val);

            if(node.right!=null) stack.push(node.right);
            if(node.left!=null) stack.push(node.left);
        }

        return res;
    }
后序遍历 leetcode145

根据前序遍历而来

前序遍历:中左右 把左右节点顺序交换 再反转数组,得到后续遍历

中左右------》 中右左------------》 左右中

public List<Integer> postorderTraversal(TreeNode root) {
        List<Integer> res=new ArrayList<>();
        if(root==null) return res;

        Stack<TreeNode> stack =new Stack<>();

        stack.push(root);
        
        while(!stack.empty()){
            TreeNode node=stack.peek();
            stack.pop();

            res.add(node.val);
            if(node.left!=null) stack.push(node.left);
            if(node.right!=null) stack.push(node.right);

        }
       // System.out.println(res);
        Collections.reverse(res);

        return res;

    }
中序遍历 leetcode94题

思想:

由于访问节点的顺序和处理节点的顺序不一样

用一个指针记录当前所遍历的位置

while内的逻辑

1.当左边节点不为空的时候,就把左边的节点加入到栈中

2.当左边节点为空了 cur记录当前栈顶元素,栈顶元素出栈,加入res

3.令cur=右边节点

public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> res=new ArrayList<>();
        if(root==null) return res;

        //一直往左遍历到底
        Stack<TreeNode> stack =new Stack<>();

        //用一个指针记录遍历的位置
        TreeNode cur=root;
        while(cur!=null || !stack.empty()){
            if(cur!=null){
                //左边不为空
                stack.push(cur);
                cur=cur.left;
            }else{
                //左边为空
                cur=stack.peek();
                stack.pop();
                res.add(cur.val);
                cur=cur.right;
            }
        }
        return res;
    }

迭代法统一代码

前序

用一个空节点记录下一个节点是要被处理的元素

class Solution {
    public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> result = new LinkedList<>();
        Stack<TreeNode> st = new Stack<>();
        if (root != null) st.push(root);
        while (!st.empty()) {
            TreeNode node = st.peek();
            if (node != null) {
                st.pop(); // 将该节点弹出,避免重复操作,下面再将右中左节点添加到栈中
                if (node.right!=null) st.push(node.right);  // 添加右节点(空节点不入栈)
                if (node.left!=null) st.push(node.left);    // 添加左节点(空节点不入栈)
                st.push(node);                          // 添加中节点
                st.push(null); // 中节点访问过,但是还没有处理,加入空节点做为标记。
                
            } else { // 只有遇到空节点的时候,才将下一个节点放进结果集
                st.pop();           // 将空节点弹出
                node = st.peek();    // 重新取出栈中元素
                st.pop();
                result.add(node.val); // 加入到结果集
            }
        }
        return result;
    }
}
中序
class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> result = new LinkedList<>();
    Stack<TreeNode> st = new Stack<>();
    if (root != null) st.push(root);
    while (!st.empty()) {
        TreeNode node = st.peek();
        if (node != null) {
            st.pop(); // 将该节点弹出,避免重复操作,下面再将右中左节点添加到栈中
            if (node.right!=null) st.push(node.right);  // 添加右节点(空节点不入栈)
            st.push(node);                          // 添加中节点
            st.push(null); // 中节点访问过,但是还没有处理,加入空节点做为标记。

            if (node.left!=null) st.push(node.left);    // 添加左节点(空节点不入栈)
        } else { // 只有遇到空节点的时候,才将下一个节点放进结果集
            st.pop();           // 将空节点弹出
            node = st.peek();    // 重新取出栈中元素
            st.pop();
            result.add(node.val); // 加入到结果集
        }
    }
    return result;
}
}
后序遍历
class Solution {
   public List<Integer> postorderTraversal(TreeNode root) {
        List<Integer> result = new LinkedList<>();
        Stack<TreeNode> st = new Stack<>();
        if (root != null) st.push(root);
        while (!st.empty()) {
            TreeNode node = st.peek();
            if (node != null) {
                st.pop(); // 将该节点弹出,避免重复操作,下面再将右中左节点添加到栈中
                st.push(node);                          // 添加中节点
                st.push(null); // 中节点访问过,但是还没有处理,加入空节点做为标记。
                if (node.right!=null) st.push(node.right);  // 添加右节点(空节点不入栈)
                if (node.left!=null) st.push(node.left);    // 添加左节点(空节点不入栈)         
                               
            } else { // 只有遇到空节点的时候,才将下一个节点放进结果集
                st.pop();           // 将空节点弹出
                node = st.peek();    // 重新取出栈中元素
                st.pop();
                result.add(node.val); // 加入到结果集
            }
        }
        return result;
   }
}

你可能感兴趣的:(代码随想录刷题记录,算法,数据结构,leetcode)