GDPU 数据结构 天码行空9
实验九 哈夫曼编码
一、【实验目的】
1、理解哈夫曼树的基本概念
2、掌握哈夫曼树的构造及数据结构设计
3、掌握哈夫曼编码问题设计和实现
二、【实验内容】
1、假设用于通信的电文仅由8个字母 {a, b, c, d, e, f, g, h} 构成,它们在电文中出现的概率分别为{ 0.07, 0.19, 0.02, 0.06, 0.32, 0.03, 0.21, 0.10 },试为这8个字母设计哈夫曼编码。

提示:包含两个过程:
(1)构建哈夫曼树
(2)输出编码。
三、【实验源代码】
🍑 优先队列版
#include <iostream>
#include <queue>
#include <map>
using namespace std;// 定义结点结构体
struct Node
{Node *l; // 左孩子结点Node *r; // 右孩子结点int w; // 结点权值char letter; // 字符// 结点构造函数Node(Node* _l, Node* _r, int _w, char _letter){l = _l;r = _r;w = _w;letter = _letter;}// 重载小于运算符bool operator < (const Node& cmp) const {return w > cmp.w;}
};priority_queue<Node> heap; // 定义优先队列用于构建哈夫曼树的堆
map<char, string> hafCode; // 存储哈夫曼编码的映射表// 构建哈夫曼树
Node* build()
{while (heap.size() > 1){// 从堆中取出两个权值最小的结点,合并为一个新的父结点Node* x = new Node(heap.top().l, heap.top().r, heap.top().w, heap.top().letter);heap.pop();Node* y = new Node(heap.top().l, heap.top().r, heap.top().w, heap.top().letter);heap.pop();Node* node = new Node(x, y, x->w + y->w, '!'); // 父结点的字符设为'!'heap.push(*node); // 将新父结点加入堆中}return new Node(heap.top().l, heap.top().r, heap.top().w, heap.top().letter); // 返回哈夫曼树的根结点
}// 递归遍历哈夫曼树,生成哈夫曼编码
void dfs(Node* n, string m)
{if (n->letter != '!'){hafCode.insert(make_pair(n->letter, m)); // 将字符和其对应的哈夫曼编码插入映射表}if (n->l != NULL)dfs(n->l, m + "0"); // 左孩子结点编码为m + "0"if (n->r != NULL)dfs(n->r, m + "1"); // 右孩子结点编码为m + "1"
}// 输出字符的哈夫曼编码
void printHafCode()
{for (char i = 'a'; i <= 'h'; i++)cout << "字母 " << i << " 的哈夫曼码值是: " << hafCode[i] << endl;
}int main()
{// 将初始字符权值放入优先队列中heap.push(Node(NULL, NULL, 7, 'a'));heap.push(Node(NULL, NULL, 19,'b'));heap.push(Node(NULL, NULL, 2, 'c'));heap.push(Node(NULL, NULL, 6, 'd'));heap.push(Node(NULL, NULL, 32,'e'));heap.push(Node(NULL, NULL, 3, 'f'));heap.push(Node(NULL, NULL, 21,'g'));heap.push(Node(NULL, NULL, 10,'h'));Node *root = build(); // 构建哈夫曼树dfs(root, ""); // 生成哈夫曼编码printHafCode(); // 输出哈夫曼编码return 0;
}
🍑 能跑就行
#include <iostream>
using namespace std;
#include <cstdio>
#include <cstring>
typedef struct node { //哈夫曼树中单个节点的信息int parent; //父节点char letter; //字母int lchild;int rchild;double weight; //权值
}*HuffmanTree;
void Select(HuffmanTree& tree, int n, int& s1, int& s2) { //找到权值最小的两个值的下标,其中s1的权值小于s2的权值int min = 0;for (int i = 1; i <= n; i++) {if (tree[i].parent == 0) {min = i;break;}}for (int i = min + 1; i <= n; i++) {if (tree[i].parent == 0 && tree[i].weight < tree[min].weight)min = i;}s1 = min; //找到第一个最小值,并赋给s1for (int i = 1; i <= n; i++) {if (tree[i].parent == 0 && i != s1) {min = i;break;}}for (int i = min + 1; i <= n; i++) {if (tree[i].parent == 0 && i != s1 && tree[i].weight < tree[min].weight)min = i;}s2 = min; //找到第二个最小值,并赋给s2
}
void CreateHuff(HuffmanTree& tree, char* letters, double* weights, int n) {int m = 2 * n - 1; //若给定n个数要求构建哈夫曼树,则构建出来的哈夫曼树的结点总数为2n-1tree = (HuffmanTree)calloc(m + 1, sizeof(node)); //开辟空间顺序储存Huffman树,用calloc开辟的空间初始化的值为0(NULL),符合Huffman树初始化条件(parent、weight、lchild、rchild等初始化应为0),由于tree[0]不存数据(因为任何节点的父节点若为0,会与节点初始化0值相混淆,故不存数据),则要开辟(2n-1)+1个空间(额外开辟一个空间)for (int i = 1; i <= n; i++) { //给节点赋字母及其对应的权值tree[i].weight = weights[i - 1];tree[i].letter = letters[i];}for (int i = n + 1; i <= m; i++) {int s1 = 0, s2 = 0;Select(tree, i - 1, s1, s2); //每次循环选择权值最小的s1和s2,生成它们的父结点tree[i].weight = tree[s1].weight + tree[s2].weight; //新创建的节点i 的权重是s1和s2的权重之和tree[i].lchild = s1; //新创建的节点i 的左孩子是s1tree[i].rchild = s2; //新创建的节点i 的右孩子是s2tree[s1].parent = i; //s1的父亲是新创建的节点itree[s2].parent = i; //s2的父亲是新创建的节点i}
}
void HuffmanCoding(HuffmanTree& tree, char**& HuffCode, int n) {HuffCode = (char**)malloc(sizeof(char*) * (n + 1)); //运用char型二级指针,可理解成包含多个char*地址的数组,开n+1个空间,因为下标为0的空间不用char* tempcode = (char*)malloc(sizeof(char) * n);tempcode[n - 1] = '\0';for (int i = 1; i <= n; i++) {int start = n - 1;int doing = i; //doing为正在编码的数据节点int parent = tree[doing].parent; //找到该节点的父结点while (parent) { //直到父结点为0(NULL),即父结点为根结点时停止if (tree[parent].lchild == doing) //如果该结点是其父结点的左孩子,则编码为0,否则为1tempcode[--start] = '0';elsetempcode[--start] = '1';doing = parent; //继续往上进行编码parent = tree[parent].parent;}HuffCode[i] = (char*)malloc(sizeof(char) * (n - start)); //开辟用于存储编码的内存空间strcpy(HuffCode[i], &tempcode[start]); //将编码拷贝到字符指针数组中的相应位置}free(tempcode); //释放辅助空间
}
int main() {int n = 8;char letters[9] = {' ','a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'};double weights[9] = {0.07, 0.19, 0.02, 0.06, 0.32, 0.03, 0.21, 0.10};HuffmanTree tree;CreateHuff(tree, letters, weights, n); //构建哈夫曼树char** HuffCode;HuffmanCoding(tree, HuffCode, n);for (int i = 1; i <= n; i++)printf("字母 %c 的哈夫曼编码值是: %s\n", tree[i].letter, HuffCode[i]);return 0;
}
👨🏫 参考资料
相关文章:
GDPU 数据结构 天码行空9
实验九 哈夫曼编码 一、【实验目的】 1、理解哈夫曼树的基本概念 2、掌握哈夫曼树的构造及数据结构设计 3、掌握哈夫曼编码问题设计和实现 二、【实验内容】 1、假设用于通信的电文仅由8个字母 {a, b, c, d, e, f, g, h} 构成,它们在电文中出现的概率分别为{ 0.…...
ISP算法——UVNR
ISP算法——UVNR 概念简介 UVNR也就是经过CSC只有在YUV域对UV两个色域进行降噪,在有些方案里也叫CNR(chroma noise reduction)。主要就是在YUV域针对彩燥进行特殊处理的一系列算法。 关于噪声产生的原因在前面关于降噪的文章和视频中已经做…...
双十一“静悄悄”?VR购物拉满沉浸式购物体验
以往每年的双十一,都会因为电商购物狂欢而变得热闹非凡,而各大电商平台也会在这天推出各种促销活动。但是,近几年来,双十一正在变得“静悄悄”。一个原因是消费群体越发理性消费,更加重视商品本身的质量和体验…...
(动手学习深度学习)第13章 计算机视觉---图像增广与微调
13.1 图像增广 总结 数据增广通过变形数据来获取多样性从而使得模型泛化性能更好常见图片增广包裹翻转、切割、变色。 图像增广代码实现...
Linux安装MySQL8.0服务
Linux安装MySQL8.0服务 文章目录 Linux安装MySQL8.0服务一、卸载1.1 查看mariadb1.2 卸载 二、安装2.1 下载2.2 上传2.3 解压2.4 重命名2.5 删除2.6 创建目录2.7 环境变量2.8 修改配置2.9 配置文件2.9 用户与用户组2.10 初始化2.11 其它 三、开启远程连接MySQL 一、卸载 首先第…...
地区 IP 库
地区 & IP 库 yudao-spring-boot-starter-biz-ip (opens new window)业务组件,提供地区 & IP 库的封装。 #1. 地区 AreaUtils (opens new window)是地区工具类,可以查询中国的省、市、区县,也可以查询国外的国家。 它的数据来自 …...
MySQL查询语句练习题,测试基本够用了
1.创建student和score表 CREATE TABLE student ( id INT(10) NOT NULL UNIQUE PRIMARY KEY , name VARCHAR(20) NOT NULL , sex VARCHAR(4) , birth YEAR, department VARCHAR(20) , address VARCHAR(50) ); 创建score表。SQL代码如下: CREATE TA…...
删除word最后一页之后的空白页
最近编辑word比较多,有时最后一页(最后一页内容还有可能是表格)之后,还有一页空白页,单独按下backspace、del都删不掉,很让人着急。 经过查询有几种方法: (1)点击选中空…...
基于站点、模式、遥感多源降水数据融合实践技术应用
降水在水循环中发挥着重要作用,塑造了生态景观和生态系统。目前,有四种主要方式获取降水数据:1)雨量计观测,2)地基雷达遥感,3)卫星遥感,4)模式模拟。基于雨量…...
html与django实现多级数据联动
html与django实现多级数据联动 1、流程 1、进入页面后先获取年级数据 2、选择年级后获取院级数据 3、选择院级后获取层次数据 4、选择层次数据后获取专业数据 2、html代码 <p style"margin-top: 10px;"><label>年级</label><select id"…...
网络安全-黑客技术-小白学习
1.网络安全是什么 网络安全可以基于攻击和防御视角来分类,我们经常听到的 “红队”、“渗透测试” 等就是研究攻击技术,而“蓝队”、“安全运营”、“安全运维”则研究防御技术。 2.网络安全市场 一、是市场需求量高; 二、则是发展相对成熟…...
.NET关于 跳过SSL中遇到的问题
一、事件的起因: 起因:开发项目过程中,可能会遇到 调用其他系统的接口 以及 代码中历史开发人员留下的IP接口访问等问题,后面该项目由自己负责,其他系统全部迁移到容器里面,只提供域名去访问。 问题:访问已迁移到容器其他系统,那么用IP地址访问肯定无法调用成功,只能用…...
fpga时序相关概念与理解
一、基本概念理解 对于数字系统而言,建立时间(setup time)和保持时间(hold time)是数字电路时序的基础。数字电路系统的稳定性,基本取决于时序是否满足建立时间和保持时间。 建立时间Tsu:触发器…...
安卓常见设计模式12------观察者模式(Kotlin版、Livedata、Flow)
1. W1 是什么,什么是观察者模式? 观察者模式(Observer Pattern)是一种行为型设计模式,用于实现组件间的松耦合通信。主要对象有观察者接口(Observer)和可观察对象(Observable&…...
USB偏好设置-Android13
USB偏好设置 1、USB偏好设置界面和入口2、USB功能设置2.1 USB功能对应模式2.2 点击设置2.3 广播监听刷新 3、日志开关3.1 Evet日志3.2 代码中日志开关3.3 关键日志 4、异常 1、USB偏好设置界面和入口 设置》已连接的设备》USB packages/apps/Settings/src/com/android/setting…...
Ubuntu 22.04 (WSL) 安装 libssl1.1
废话不多说!!! 步骤一: echo "deb http://security.ubuntu.com/ubuntu focal-security main" | sudo tee /etc/apt/sources.list.d/focal-security.list 步骤二: sudo apt-get update 步骤三:…...
数据结构-图的课后习题(2)
题目要求: 对于下面的这个无向网,给出: 1.“深度优先搜索序列”(从V1开始) 2.“广度优先序列”(从V1开始) 3.“用Prim算法求最小生成树” 代码实现: 1.深度优先搜索:…...
[Machine Learning] 多任务学习
文章目录 基于参数的MTL模型 (Parameter-based MTL Models)基于特征的MTL模型 (Feature-based MTL Models)基于特征的MTL模型 I:基于特征的MTL模型 II: 基于特征和参数的MTL模型 (Feature- and Parameter-based MTL Models) 多任务学习 (Multi-task Lear…...
【C语言从入门到放弃 6】递归,强制类型转换,可变参数和错误处理详解
C语言是一种功能强大的编程语言,具有许多高级特性,包括强制类型转换,递归,可变参数和错误处理。在本文中,我们将深入了解这些特性,并提供简单的示例来帮助理解。 递归 递归是一种函数调用自身的技术&…...
使用LLama和ChatGPT为多聊天后端构建微服务
微服务架构便于创建边界明确定义的灵活独立服务。这种可扩展的方法使开发人员能够在不影响整个应用程序的情况下单独维护和完善服务。然而,若要充分发挥微服务架构的潜力、特别是针对基于人工智能的聊天应用程序,需要与最新的大语言模型(LLM&…...
day52 ResNet18 CBAM
在深度学习的旅程中,我们不断探索如何提升模型的性能。今天,我将分享我在 ResNet18 模型中插入 CBAM(Convolutional Block Attention Module)模块,并采用分阶段微调策略的实践过程。通过这个过程,我不仅提升…...
Auto-Coder使用GPT-4o完成:在用TabPFN这个模型构建一个预测未来3天涨跌的分类任务
通过akshare库,获取股票数据,并生成TabPFN这个模型 可以识别、处理的格式,写一个完整的预处理示例,并构建一个预测未来 3 天股价涨跌的分类任务 用TabPFN这个模型构建一个预测未来 3 天股价涨跌的分类任务,进行预测并输…...
AspectJ 在 Android 中的完整使用指南
一、环境配置(Gradle 7.0 适配) 1. 项目级 build.gradle // 注意:沪江插件已停更,推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...
ABAP设计模式之---“简单设计原则(Simple Design)”
“Simple Design”(简单设计)是软件开发中的一个重要理念,倡导以最简单的方式实现软件功能,以确保代码清晰易懂、易维护,并在项目需求变化时能够快速适应。 其核心目标是避免复杂和过度设计,遵循“让事情保…...
TSN交换机正在重构工业网络,PROFINET和EtherCAT会被取代吗?
在工业自动化持续演进的今天,通信网络的角色正变得愈发关键。 2025年6月6日,为期三天的华南国际工业博览会在深圳国际会展中心(宝安)圆满落幕。作为国内工业通信领域的技术型企业,光路科技(Fiberroad&…...
【LeetCode】算法详解#6 ---除自身以外数组的乘积
1.题目介绍 给定一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O…...
何谓AI编程【02】AI编程官网以优雅草星云智控为例建设实践-完善顶部-建立各项子页-调整排版-优雅草卓伊凡
何谓AI编程【02】AI编程官网以优雅草星云智控为例建设实践-完善顶部-建立各项子页-调整排版-优雅草卓伊凡 背景 我们以建设星云智控官网来做AI编程实践,很多人以为AI已经强大到不需要程序员了,其实不是,AI更加需要程序员,普通人…...
Copilot for Xcode (iOS的 AI辅助编程)
Copilot for Xcode 简介Copilot下载与安装 体验环境要求下载最新的安装包安装登录系统权限设置 AI辅助编程生成注释代码补全简单需求代码生成辅助编程行间代码生成注释联想 代码生成 总结 简介 尝试使用了Copilot,它能根据上下文补全代码,快速生成常用…...
Linux中INADDR_ANY详解
在Linux网络编程中,INADDR_ANY 是一个特殊的IPv4地址常量(定义在 <netinet/in.h> 头文件中),用于表示绑定到所有可用网络接口的地址。它是服务器程序中的常见用法,允许套接字监听所有本地IP地址上的连接请求。 关…...
C#中用于控制自定义特性(Attribute)
我们来详细解释一下 [AttributeUsage(AttributeTargets.Class, AllowMultiple false, Inherited false)] 这个 C# 属性。 在 C# 中,Attribute(特性)是一种用于向程序元素(如类、方法、属性等)添加元数据的机制。Attr…...
