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

发布于:2025-06-23 ⋅ 阅读:(15) ⋅ 点赞:(0)

在这里插入图片描述
在这里插入图片描述



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 + " ");
        }
    }
}


网站公告

今日签到

点亮在社区的每一天
去签到