华为OD机考-生成哈夫曼树-二叉树(JAVA 2025B卷)


java 复制代码
import java.util.*;

 class HuffmanNode implements Comparable<HuffmanNode> {
    int weight;
    HuffmanNode left, right;

    HuffmanNode(int weight) {
        this.weight = weight;
        this.left = this.right = null;
    }

    @Override
    public int compareTo(HuffmanNode other) {
        return this.weight - other.weight;
    }
}

public class HuffmanTree {
    /**
     * 构建哈夫曼树
     * 哈夫曼树是一种带权路径长度最短的二叉树,也称为最优二叉树
     * 在数据压缩、编码等领域有广泛的应用
     *
     * @param weights 每个节点的权重,权重越小的节点,在构建哈夫曼树时,越靠近根节点
     * @return 返回哈夫曼树的根节点
     */
    public static HuffmanNode buildHuffmanTree(int[] weights) {
        // 优先队列,用于存储哈夫曼树的节点,队列头部元素权值最小
        PriorityQueue<HuffmanNode> pq = new PriorityQueue<>();

        // 遍历所有节点权重,初始化哈夫曼树节点并加入优先队列
        for (int weight : weights) {
            pq.add(new HuffmanNode(weight));
        }

        // 当优先队列中节点数量大于1时,循环构建哈夫曼树
        while (pq.size() > 1) {
            // 从优先队列中取出权值最小的两个节点
            HuffmanNode left = pq.poll();
            HuffmanNode right = pq.poll();

            // 断言right节点非空,确保树能正常构建
            assert right != null;
            // 创建新的哈夫曼节点,作为left和right节点的父节点,其权重为两个子节点权重之和
            HuffmanNode parent = new HuffmanNode(left.weight + right.weight);

            // 设置父节点的左右子节点
            parent.left = left;
            parent.right = right;

            // 将新的父节点加入优先队列
            pq.add(parent);
        }

        // 返回优先队列中剩余的唯一节点,即哈夫曼树的根节点
        return pq.poll();
    }


    /**
     * 中序遍历哈夫曼树
     * 中序遍历的特点是左子树-根节点-右子树的顺序访问树中的节点
     * 这种遍历顺序在哈夫曼树中主要用于验证树的结构,而不用于构建最短编码
     *
     * @param root 哈夫曼树的根节点
     * @param result 用于存储遍历结果的列表,通常是节点的权重
     */
    public static void inorderTraversal(HuffmanNode root, List<Integer> result) {
        // 判断当前节点是否为空,为空则直接返回
        if (root == null) {
            return;
        }

        // 递归中序遍历左子树
        inorderTraversal(root.left, result);

        // 将当前节点的权重添加到结果列表中
        result.add(root.weight);

        // 递归中序遍历右子树
        inorderTraversal(root.right, result);
    }


    /**
     * 主函数入口
     * 本程序用于演示霍夫曼树的构建及其遍历过程
     * 霍夫曼树是一种带权路径长度最短的二叉树,具有重要应用价值
     *
     * @param args 命令行参数
     */
    public static void main(String[] args) {
        // 创建Scanner对象,用于读取命令行输入
        Scanner scanner = new Scanner(System.in);

        // 读取霍夫曼树节点数量
        int n = scanner.nextInt();
        // 初始化霍夫曼树节点权重数组
        int[] weights = new int[n];

        // 读取每个节点的权重
        for (int i = 0; i < n; i++) {
            weights[i] = scanner.nextInt();
        }

        // 构建霍夫曼树并返回根节点
        HuffmanNode root = buildHuffmanTree(weights);

        // 初始化用于存储中序遍历结果的列表
        List<Integer> result = new ArrayList<>();

        // 中序遍历霍夫曼树,并将结果存储到列表中
        inorderTraversal(root, result);

        // 输出中序遍历结果
        for (int weight : result) {
            System.out.print(weight + " ");
        }
    }
}
相关推荐
装不满的克莱因瓶1 小时前
【踩坑】IDEA提交Git .gitignore忽略文件不起作用
java·git·.gitignore·踩坑
superman超哥1 小时前
Rust 异步错误处理最佳实践
开发语言·rust·编程语言·rust异步错误处理·rust最佳实践
专注于大数据技术栈1 小时前
java学习--Collection的迭代器
java·python·学习
脏脏a1 小时前
C++ STL list 模拟实现:从底层链表到容器封装
开发语言·c++·stl·双链表
毕设源码-郭学长8 小时前
【开题答辩全过程】以 基于SpringBoot技术的美妆销售系统为例,包含答辩的问题和答案
java·spring boot·后端
故事不长丨8 小时前
C#正则表达式完全攻略:从基础到实战的全场景应用指南
开发语言·正则表达式·c#·regex
梨落秋霜8 小时前
Python入门篇【文件处理】
android·java·python
Java 码农8 小时前
RabbitMQ集群部署方案及配置指南03
java·python·rabbitmq
哈库纳玛塔塔9 小时前
放弃 MyBatis,拥抱新一代 Java 数据访问库
java·开发语言·数据库·mybatis·orm·dbvisitor
phltxy9 小时前
从零入门JavaScript:基础语法全解析
开发语言·javascript