二叉树操作全解析:从递归到层序遍历

二叉树的基本操作

二叉树的类由节点的值,节点的左枝,节点的友枝

java 复制代码
import java.util.LinkedList;
import java.util.Queue;

/**
 * 二叉树节点类
 */
class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;
    
    TreeNode(int val) {
        this.val = val;
        this.left = null;
        this.right = null;
    }
    
    TreeNode(int val, TreeNode left, TreeNode right) {
        this.val = val;
        this.left = left;
        this.right = right;
    }
}

方法说明:

  1. size() - 递归计算节点总数
  2. getLeafNodeCount() - 计算叶子节点(没有子节点的节点)数量
  3. getKLevelNodeCount() - 计算指定层数的节点数量
  4. getHeight() - 计算树的高度(深度)
  5. find() - 查找指定值的节点
  6. levelOrder() - 层序遍历(广度优先遍历)
  7. isCompleteTree() - 判断是否为完全二叉树

时间复杂度分析:

  • 所有方法的时间复杂度都是 O(n),其中 n 是节点数
  • 空间复杂度:递归方法为 O(h)(h为树高),层序遍历方法为 O(w)(w为树的最大宽度)

使用建议:

  • 对于大型二叉树,注意递归深度可能导致的栈溢出问题
  • 层序遍历使用队列,适合需要按层处理节点的场景
  • 完全二叉树的判断算法利用了层序遍历的特性

1. 获取树中节点的个数

时间复杂度:O(n),需要遍历所有节点

空间复杂度:O(h),递归栈深度为树的高度

java 复制代码
public int size(TreeNode root) {
        if(root == null){
            return 0;
        }
        return size(root.left) + size(root.right) + 1;
}

2. 获取叶子节点的个数

叶子节点:没有子节点的节点

java 复制代码
public int getLeafNodeCount(TreeNode root) {
        if (root == null){
            return 0;
        }
        if (root.left == null && root.right == null){
            // 当前节点是叶子节点
            return 1;
        }
        // 递归计算左右子树的叶子节点数
        return getLeafNodeCount(root.left) + getLeafNodeCount(root.right);
}

3. 获取第K层节点的个数

java 复制代码
/**
     * @param root 根节点
     * @param k 目标层数(从1开始计数)
     */
public int getKLevelNodeCount(TreeNode root, int k) {
        if (root == null || k <= 0) {
            return 0;
        }
        if (k == 1) {
            // 第1层只有根节点
            return 1;
        }
        // 第k层节点数 = 左子树的第k-1层节点数 + 右子树的第k-1层节点数
        return getKLevelNodeCount(root.left,k-1) + getKLevelNodeCount(root.right,k-1);
}

4. 获取二叉树的高度(深度)

高度:从根节点到最远叶子节点的最长路径上的节点数

java 复制代码
public int getHeight(TreeNode root) {
        if (root == null) {
            return 0;
        }
        // 当前节点高度 = 1 + max(左子树高度, 右子树高度)
       return Math.max(getHeight(root.left),getHeight(root.right)) + 1;
}

5. 检测值为value的元素是否存在

java 复制代码
public TreeNode find(TreeNode root, int val) {
        if (root == null){
            return null;
        }
        if(root.val == val){
            return root;
        }
        // 先在左子树中查找
        TreeNode left = find(root.left,val);
        if(left != null){
            return root;
        }
        // 左子树没找到,再在右子树中查找
        return find(root.right,val);
}

6. 层序遍历(广度优先遍历)

java 复制代码
public void levelOrder(TreeNode root) {
        if(root == null){
            System.out.println("空树");
        }
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        while (queue.peek() != null){
            queue.offer(queue.peek().left);
            queue.offer(queue.peek().right);
            System.out.print(queue.poll().val+" ");
        }
        System.out.println();    
}

7. 判断一棵树是不是完全二叉树

完全二叉树:除了最后一层,其他层都是满的,且最后一层的节点都靠左排列

java 复制代码
public boolean isCompleteTree(TreeNode root) {
        if (root == null) {
            return true;
        }
        
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        boolean reachedEnd = false; // 标记是否遇到了第一个空节点
        
        while (!queue.isEmpty()) {
            TreeNode current = queue.poll();
            
            if (current == null) {
                // 遇到空节点,标记为已到达末尾
                reachedEnd = true;
            } else {
                // 如果已经遇到过空节点,又遇到了非空节点,说明不是完全二叉树
                if (reachedEnd) {
                    return false;
                }
                // 将左右子节点加入队列(即使是null也要加入)
                queue.offer(current.left);
                queue.offer(current.right);
            }
        }
        
        return true;
}

测试

java 复制代码
public class Test {
    public static void main(String[] args) {
        // 构建测试二叉树
        //       1
        //      / \
        //     2   3
        //    / \   \
        //   4   5   6
        TreeNode root = new TreeNode(1);
        root.left = new TreeNode(2);
        root.right = new TreeNode(3);
        root.left.left = new TreeNode(4);
        root.left.right = new TreeNode(5);
        root.right.right = new TreeNode(6);


        // 测试各个方法
        System.out.println("节点总数: " + root.size(root));
        System.out.println("叶子节点数: " + root.getLeafNodeCount(root));
        System.out.println("第2层节点数: " + root.getKLevelNodeCount(root, 2));
        System.out.println("树的高度: " + root.getHeight(root));

        TreeNode found = root.find(root, 5);
        System.out.println("查找值为5的节点: " + (found != null ? "找到,值为" + found.val : "未找到"));

        root.levelOrder(root);
        System.out.println("是否是完全二叉树: " + root.isCompleteTree(root));

        // 修改树结构使其成为完全二叉树
        root.right.left = new TreeNode(7);
        System.out.println("修改后是否是完全二叉树: " + root.isCompleteTree(root));
    }
}
相关推荐
Chester_199913 小时前
CSP202203C.计算资源调度器
开发语言·数据结构·c++·蓝桥杯
裕晟资质规划14 小时前
武器装备科研生产单位保密资质申请方法论:条件模型与流程拆解
人工智能·算法
EXI-小洲14 小时前
Java 操作 Word:字符串替换、图片插入、动态生成表格与API接口下载
java·开发语言·spring boot·word
2601_9619017015 小时前
SpringBoot使用Nacos进行application.yml配置管理
java·spring boot·spring
en.en..16 小时前
C语言 标准输入 / 输出缓冲区
算法
何以解忧,唯有..16 小时前
LangChain 工具调用(Tool Calling)实战指南
java·前端·langchain
QQ_216962909617 小时前
【源码编号:project79475】SpringBoot校内二手交易平台:商品发布、分类检索、留言交流、订单管理全流程实战
java·spring boot·后端
吃好睡好便好17 小时前
查找函数的使用
学习·算法·matlab·生活·查找函数
学习星球17 小时前
单调栈——从“找下一个更大的“到柱状图中的最大矩形
数据库·c++·算法·leetcode·xcode
前端 贾公子18 小时前
第09章:上下文与记忆 (2)
java·服务器·前端