华为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 + " ");
        }
    }
}
相关推荐
应用市场11 分钟前
Qt QTreeView深度解析:从原理到实战应用
开发语言·数据库·qt
q***965819 分钟前
Spring Data JDBC 详解
java·数据库·spring
ooooooctober22 分钟前
PHP代码审计框架性思维的建立
android·开发语言·php
Kuo-Teng22 分钟前
LeetCode 118: Pascal‘s Triangle
java·算法·leetcode·职场和发展·动态规划
倚肆34 分钟前
HttpServletResponse 与 ResponseEntity 详解
java·后端·spring
悟能不能悟35 分钟前
java List怎么转换为Vector
java·windows·list
yaoxin52112336 分钟前
241. Java 集合 - 使用 Collections 工厂类处理集合
java·windows
依_旧39 分钟前
【玩转全栈】----Django基本配置和介绍
java·后端
864记忆39 分钟前
Qt Widgets 模块中的函数详解
开发语言·qt
white-persist44 分钟前
差异功能定位解析:C语言与C++(区别在哪里?)
java·c语言·开发语言·网络·c++·安全·信息可视化