华为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 + " ");
        }
    }
}
相关推荐
我命由我1234512 分钟前
C++ - 标准库之 <string> npos(npos 概述、npos 的作用)
服务器·c语言·开发语言·c++·后端·visualstudio·visual studio
君鼎15 分钟前
C++项目经验与解决问题能力需知
开发语言·c++
带刺的坐椅24 分钟前
Solon Expression Language (SnEL):轻量高效的Java表达式引擎
java·solon·snel·表达式语言
老马啸西风29 分钟前
从零开始手写redis(18)缓存淘汰算法 FIFO 优化
java
IT艺术家-rookie31 分钟前
golang--数据类型与存储
开发语言·后端·golang
Java中文社群42 分钟前
超实用!SpringAI提示词的4种神级用法
java·人工智能·后端
双叶8361 小时前
(C++)素数的判断(C++教学)(C语言)
c语言·开发语言·数据结构·c++·算法
代码or搬砖1 小时前
Spring JDBC配置与讲解
java·数据库·spring
魔芋红茶1 小时前
Spring 源码学习 3:工厂后处理器
java·学习·spring
m0_634865401 小时前
sa-token:我将代替你,Spring Security
java·后端·spring