【Java】构建哈夫曼树和输出哈夫曼编码

news2025/1/23 20:44:35

问题背景

一个单位有12个部门,每个部门都有一部电话,但是整个单位只有一根外线,当有电话打过来的时候,由转接员转到内线电话,已知各部门使用外线电话的频率为(次/天):5 20 10 12 8 43 5 6 9 15 19 32。

利用哈夫曼树算法思想设计内线电话号码,使得接线员拨号次数尽可能少。要求:

(1)依据使用外线电话的频率构造二叉树;

(2)输出设计出的各部门内线电话号码。

思路描述

  • 构建哈夫曼树:将所有节点按权重值从小到大排序,从中取出最小的两个节点node1、node2,然后创建一个新的节点,新节点的左右子节点分别是node1、node2(左节点node1的权重值一定要比右节点node2小),新节点的权重值是node1和node2权重值之和,然后将新节点代替node1和node2加入节点队列中,重复该过程,直到节点队列中只剩下一个节点。
  • 输入哈夫曼编码:在前面的构建好的二叉树中,左分支上标记0,右分支上标注1,从根节点到叶子节点所走过的路径就是该叶子节点的哈夫曼编码

 代码实现

/**
 * 用二叉链表存储二叉树
 */
public class HTNode implements Comparable<HTNode>{
    int weight;//权重
    HTNode left,right;//左右子节点

    public HTNode(int weight) {
        this.weight = weight;
    }

    @Override
    public int compareTo(HTNode o) {
        return this.weight-o.weight;//从小到大排序
    }
    @Override
    public String toString() {
        return super.toString();
    }
}
public class HuffmanTree {
    //构建哈夫曼树
    public static HTNode CreatHuffmanTree(int[] arr){
        //初始化
        if(arr.length<1)
            return null;
        List<HTNode> nodes=new ArrayList<>();
        for(int weight:arr){
            nodes.add(new HTNode(weight));
        }
        Collections.sort(nodes);//HTNodes实现了Comparable接口,基于weight排序
        while (nodes.size()>1){//nodes中只剩下一个时,该节点就是根节点
            //取权值最小的两个结点
            HTNode htNode1 = nodes.get(0);
            HTNode htNode2 = nodes.get(1);

            HTNode parent=new HTNode(htNode1.weight+htNode2.weight);
            parent.left=htNode1;
            parent.right=htNode2;
            nodes.remove(0);
            nodes.remove(0);
            nodes.add(parent);
            Collections.sort(nodes);
        }

        return nodes.get(0);
    }

    public static void creatHuffmanCode(HTNode root,String append,StringBuilder code){
        StringBuilder stringBuilder = new StringBuilder(code);
        stringBuilder.append(append);
        if(root.left==null&&root.right==null){
            System.out.println("权值为"+root.weight+"的节点的哈夫曼编码为"+stringBuilder);
            return;
        }
        creatHuffmanCode(root.left,"0",stringBuilder);
        creatHuffmanCode(root.right,"1",stringBuilder);
    }
    //写个前序遍历验证一下构建的哈夫曼树是否正确
    public static void preOrder(HTNode node){
        if(node==null)
            return;
        System.out.print(node.weight+" ");
        preOrder(node.left);
        preOrder(node.right);
    }
}

 运行结果

public class Main {
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        System.out.println("请输入节点个数:");
        int n=sc.nextInt();
        int[] arr = new int[n];
        System.out.println("请输入"+n+"个节点的权值:");
        for(int i=0;i<n;i++){
            arr[i]=sc.nextInt();
        }
        HTNode htNode = HuffmanTree.CreatHuffmanTree(arr);
        System.out.println("前序遍历该哈夫曼树:");
        HuffmanTree.preOrder(htNode);
        System.out.println();
        HuffmanTree.creatHuffmanCode(htNode,"",new StringBuilder());
    }
}

 

 另外

  1. 为什么哈夫曼编码能够保证是前缀编码?                                                                              要编码的字符都在叶子结点上,根结点到每一个叶子结点的路径一定是不同的
  2.  为什么哈夫曼编码能够保证字符编码总长最短?                                                                   哈夫曼树的带权路径长度是最小的,权重越大出现频率越高的字符越接近根结点

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1297724.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

算法Day23 简单吃饭(0-1背包)

简单吃饭&#xff08;0-1背包&#xff09; Description Input Output Sample 代码 import java.util.Scanner; public class Main {public static void main(String[] args) {Scanner scanner new Scanner(System.in);int n scanner.nextInt();int total scanner.nextInt(…

Java一对一聊天程序

我们首先要完成服务端&#xff0c;不然出错&#xff0c;运行也要先运行服务端&#xff0c;如果不先连接服务端&#xff0c;就不监听&#xff0c;那客户端不知道连接谁 服务端 import java.awt.BorderLayout; import java.awt.event.ActionEvent; import java.awt.event.Actio…

Qt之QSlider和QProgressBar

Qt之QSlider和QProgressBar 实验结果 #include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent) :QWidget(parent),ui(new Ui::Widget) {ui->setupUi(this);connect(ui->dial,&QDial::valueChanged,this,&Widget::do_val…

Redis rdb源码解析

前置学习&#xff1a;Redis server启动源码-CSDN博客 1、触发时机 1、执行save命令--->rdbSave函数 2、执行bgsave命令--->rdbSaveBackground函数或者&#xff08;serverCron->prepareForShutdown&#xff09; 3&#xff0c;主从复制-->startBgsaveForReplication…

序列的Z变换(信号的频域分析)

1. 关于Z变换 2. 等比级数求和 3. 特殊序列的Z变换 4. 因果序列/系统收敛域的特点 5. 例题

C/C++,树算法——二叉树的插入、移除、合并及遍历算法之源代码

1 文本格式 #include<iostream>; using namespace std; // A BTree node class BTreeNode { int* keys; // An array of keys int t; // Minimum degree (defines the range for number of keys) BTreeNode** C; // An array of child pointers …

Redis 命令全解析之 Hash类型

文章目录 ⛄介绍⛄命令⛄RedisTemplate API⛄应用场景 ⛄介绍 Hash类型&#xff0c;也叫散列&#xff0c;其value是一个无序字典&#xff0c;类似于Java中的 HashMap 结构。 String结构是将对象序列化为JSON字符串后存储&#xff0c;当需要修改对象某个字段时很不方便&#xf…

redis集群(cluster)笔记

1. 定义&#xff1a; 由于数据量过大&#xff0c;单个Master复制集难以承担&#xff0c;因此需要对多个复制集进行集群&#xff0c;形成水平扩展每个复制集只负责存储整个数据集的一部分&#xff0c;这就是Redis的集群&#xff0c;其作用是提供在多个Redis节点间共享数据的程序…

论MYSQL注入的入门注解

&#x1f4d1;打牌 &#xff1a; da pai ge的个人主页 &#x1f324;️个人专栏 &#xff1a; da pai ge的博客专栏 ☁️宝剑锋从磨砺出&#xff0c;梅花香自苦寒来 &#x1f4d1;什么是MySQL注入&…

Win10+WSL2+Ubuntu22.04 +图形化桌面配置

一 配置WSL2 如何在 Windows 10 上安装 WSL 2 - 知乎 wsl --set-version Ubuntu 2 二 安装Ubuntu22.04 用IDM能加速下载&#xff0c;去官网下载22.04的appxbundle&#xff0c;后缀改为zip&#xff0c;这个包含各种操作系统的Ubuntu22.04的appx。我们选择x64解压就行了&…

2023-12-05 Qt学习总结2

点击 <C 语言编程核心突破> 快速C语言入门 Qt学习总结 前言五 Hello Qt!六 Qt控件和事件七 Qt信号和槽八 Qt自定义信号和槽总结 前言 要解决问题: 学习qt最核心知识, 多一个都不学. 五 Hello Qt! 现在我们已经有了一个空窗口工程, 传统上, 我们要实现一个"Hello …

104. 二叉树的最大深度(Java)

目录 解法&#xff1a; 官方解答&#xff1a; 方法一&#xff1a;深度优先搜索 方法二&#xff1a;广度优先搜索 思路与算法 复杂度分析 时间复杂度&#xff1a; 空间复杂度&#xff1a; 给定一个二叉树 root &#xff0c;返回其最大深度。 二叉树的 最大深度 是指从根…

mysql pxc高可用离线部署(三)

pxc学习流程 mysql pxc高可用 单主机 多主机部署&#xff08;一&#xff09; mysql pxc 高可用多主机离线部署&#xff08;二&#xff09; mysql pxc高可用离线部署&#xff08;三&#xff09; mysql pxc高可用 跨主机部署pxc 本文使用docker进行安装&#xff0c;主机间通过…

openGauss学习笔记-144 openGauss 数据库运维-例行维护-慢sql诊断

文章目录 openGauss学习笔记-144 openGauss 数据库运维-例行维护-慢sql诊断144.1 背景信息144.2 前提条件 openGauss学习笔记-144 openGauss 数据库运维-例行维护-慢sql诊断 144.1 背景信息 在SQL语句执行性能不符合预期时&#xff0c;可以查看SQL语句执行信息&#xff0c;便…

CGAL的3D简单网格数据结构

由具有多个曲面面片的多面体曲面生成的多域四面体网格。将显示完整的三角剖分&#xff0c;包括属于或不属于网格复合体、曲面面片和特征边的单元。 1、网格复合体、 此软件包致力于三维单纯形网格数据结构的表示。 一个3D单纯形复杂体由点、线段、三角形、四面体及其相应的组合…

BUUCTF [CISCN2019 华北赛区 Day2 Web1]Hack World 1(SQL注入之布尔盲注)

题目环境判断注入类型 1 2 3 1’ 输入1’报错提示bool(false) 可知是字符型的布尔注入&#xff08;盲注&#xff09; 尝试万能密码 1’ or ‘1’1 已检测SQL注入 猜测某些关键字或者字符被过滤 FUZZ字典爆破 可以看到部分关键字被过滤&#xff0c;包括空格 All You Want Is In …

iOS——定位与地图

平时在写项目的时候可能会遇到需要使用定位服务的地方&#xff0c;比如说获取位置和导航等。因此这里我会使用OC自带的库以及苹果系统的地图来获取定位以及显示在地图上。 开始前的设置 在获取定位前&#xff0c;需要在项目文件的info中添加两个关键字&#xff0c;用于向用户…

ooTD I 这么精致优雅的套装也太好看了吧

精致到每一个细节的国风套装 领口袖口拼接环保毛条 精美的绣花增添浓重的高级感 外套90白鸭绒填充 敲暖和裙子的门襟处 也是做了定制盘扣&#xff0c;外套和裙子单独来穿也很精致

STM32L051使用HAL库操作实例(13)- 读取IAQ-CORE-C传感器实例

目录 一、前言 二、传感器参数 三、STM32CubeMX配置&#xff08;本文使用的STM32CubeMX版本为6.1.2&#xff09;例程使用模拟I2C进行数据读取 1.MCU选型 2.使能时钟 3.时钟配置 4.GPIO口配置 四、配置STM32CubeMX生成工程文件 五、点击GENERATE CODE生成工程文件 六、…

人类的耳朵:听觉的动态范围

作者&#xff1a;听觉健康 听觉的动态范围即可用的听力范围。在坐标系中&#xff0c;它可以表示为以听阈和最大舒适级为界形成的区域&#xff0c;其坐标轴分别为频率和声压级&#xff08;刺激持续时间在某种程度上对其产生影响&#xff09;。是什么因素决定了人类听力的极限&am…