哈夫曼树和哈夫曼编码与译码

Huffman树的创建

思想概述

为求得最优二叉树,哈夫曼巧妙地涉及到哈夫曼算法。通过哈夫曼算法可以建立一棵哈夫曼树。现有n个结点,如果岸边每个结点都作为一棵二叉树的根结点,那么这个n个根结点就组成了一个森林。把结点在文件中出现的次数定义为该结点的权值。

1.在森林中取权值最小的两个根结点,合并成一棵二叉树,并生成一个新结点T,作为这两个结点的父亲,T的权值是它的两个子结点的权值之和。与此同时,森林中减少了一棵树。

2.对新森林重复上述操作,直至森林中只有唯一的根结点,最后的根结点便是所求的哈夫曼树的根。

注意:最优二叉树未必唯一,而哈夫曼树可能只是满足条件的所有最优二叉树中的一棵。

Huffman结点

假定哈夫曼树中每个结点的结构为:

LLINK/左链接INFO/信息域Weight/权值RLINK/右链接
/*Huffman结点结构体*/
typedef struct HuffmanNode {char INFO;  //信息域int Weight;  //权重HuffmanNode* LLINK;  //左链接HuffmanNode* RLINK;  //右链接
}HuffmanNode;

Huffman树

假定与给定的m个权值结合的结点的地址存在于一维数组H[1:m+1]中,并且该数组按每个结点的Weight域已排序(从小到大)。

如Huffman树结点声明所示,其中H为存储Huffman结点的一维数组(Huffman结点内存储了结点权值Weight),且数组H已排序。

/*Huffman树结构体*/
typedef struct HuffmanTree {HuffmanNode** H;  //存储Huffman结点的数组int m;  //结点个数
}HuffmanTree;

构建Huffman树 

1.初始化

创建所有结点,把每个结点都作为一棵二叉树的根结点,所有结点组成一个森林 。

2.组合

在森林中选取两个最小的结点,合并成一棵二叉树,并并生成一个新结点T,作为这两个结点的父亲,T的权值是它的两个子结点的权值之和。

3.找位置

找到H数组中合适的位置插入新生成的二叉树,使数组保持递增。

4.循环

循环操作所有结点。

HuffmanTree* CreateHuffmanTree(char data[],int weight[],int n) {//初始化HuffmanTree* tree = new HuffmanTree;tree->m = n;//每个结点都作为一棵树的根结点,组成森林for (int i = 1; i <= tree->m; i++) {tree->H[i] = new HuffmanNode;tree->H[i]->INFO = data[i];tree->H[i]->Weight = weight[i];tree->H[i]->LLINK = NULL;tree->H[i]->RLINK = NULL;}//组合过程HuffmanNode* p1, * p2,* p,* t;int i, j;for (i = 1; i < tree->m; i++) {t = new HuffmanNode;p1 = tree->H[i];p2 = tree->H[i + 1];t->LLINK = p1;t->RLINK = p2;  //链接左右结点t->Weight = p1->Weight + p2->Weight;  //权重等于子结点权重之和p = t;j = i + 2;  //从下一棵结点开始比较if (j <= tree->m && p->Weight >= tree->H[j]->Weight) {  //寻找合适的位置,使森林保持递增tree->H[j - 1] = tree->H[j];  //小的结点前移,给p结点腾位置j++;}tree->H[j - 1] = p;}return tree;
}

Huffman编码 

对于所有的编码,哈夫曼编码是文件的总编码长度最短,字符集中的字符所在的结点均是哈夫曼树中的外结点。

将哈夫曼树每个分支结点的左分支标上0,右分支标上1,把从根结点到每个叶结点的路径上的标号连接起来,作为该叶结点所代表的字符的编码。

/*Huffman编码*/
#include <unordered_map>
#include <cstring>
//使用unordered_map,char标志字符,string对应的Huffman编码
typedef unordered_map<char, string> UMCS;
UMCS HuffmanCode;  //Huffman编码
void CreateHuffmanCode(HuffmanNode* t,string code) {if (t == NULL) return;//左右子结点为空,则为叶结点,为字符if (t->LLINK == NULL && t->RLINK == NULL) {HuffmanCode[t->INFO] = code;}//递归处理左右结点,进行Huffman编码CreateHuffmanCode(t->LLINK, code + "0");  //左结点,+"0"CreateHuffmanCode(t->RLINK, code + "1");  //右结点,+"1"
}

Huffman译码

对压缩后的数据文件进行解码的过程是,依次读入文件的二进制码,从哈夫曼树的根结点出发,若当前读入0,则走向其左儿子,否则走向其右儿子,到达某一叶结点时,便可以译出相应的字符。

/*Huffman译码*/
void TransHuffmanCode(HuffmanNode* root) {HuffmanNode* t=root;string ans="";  //存储最终译码结果string code;  cin >> code;  //读入二进制Huffman编码int n = code.size();  //二进制编码的长度for (int i = 0; i < n; i++) {char ch = code[i];  if (ch == '0') t = t->LLINK;  //读入'0',则走左分支if (ch == '1') t = t->RLINK;  //读入'1',则走右分支//若走到叶结点,当前阶段译码成功,可存入一个字符if (t->LLINK == NULL && t->RLINK == NULL) {  ans = ans + t->INFO;  //串入译码结果if (i != n - 1) t = root;  //若此时还剩二进制编码未译,回到根结点,继续译码}}//若二进制编码读入完全,此时却没有走到叶结点,证明译码不完全,译码错误if (!(t->LLINK == NULL && t->RLINK == NULL))cout << "INVALID" << endl;  //译码错误,输出"INVALID"elsecout << ans<<endl;  //译码成功,输出最终译码结果
}

《数据结构》刘大友||第5章 树与二叉树||5.4压缩与哈夫曼树 

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

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

相关文章

Stable Diffusion Web UI - ControlNet 景深 Depth

Depth 的使用场景为建筑类型带有景深的场景&#xff0c;同样的针对人物也可以&#xff0c;不过 Depth 会限制人物的绘画时的自由发挥范围。 通过 Depth 可以得到类似如下的结果 从上图结果&#xff0c;可以看到&#xff0c;通过 Depth 来控制图片生成&#xff0c;整体图片的结…

UE5 随机生成地牢关卡

参考视频&#xff1a;【UE5 | 教程 | 地编】虚幻引擎5 中创建史诗级 程序化 地下城_哔哩哔哩_bilibili 首先创建一个父项Actor 这个BOX碰撞提是和地板重叠的 这三个是场景组件&#xff0c;这个ExitsFolder下面的箭头等会会在子蓝图中添加 接下来创建BP_MasterRoom的子蓝图&…

计算机网络:网络层 —— 软件定义网络 SDN

文章目录 软件定义网络 SDN远程控制器OpenFlow协议SDN 广义转发流表简单转发负载均衡防火墙 SDN 控制器 软件定义网络 SDN 软件定义网络&#xff08;Software Defined Networking&#xff0c;SDN&#xff09;是一种新兴的网络架构&#xff0c;旨在通过网络控制与数据转发的分离…

软件技术求职简历「优选篇」

【#软件技术简历#】一份精心撰写的简历是增加获得心仪职位的机会。那么&#xff0c;如何才能写出一份既全面又吸引人的软件技术简历呢&#xff1f;以下是幻主简历整理的软件技术简历「优选篇」&#xff0c;欢迎大家阅读收藏&#xff01; 软件技术简历范文&#xff1a; 求职意向…

MQTT实用示例集:Air201版

今天贴出的是Air201版关于MQTT实用示例集&#xff0c;希望大家喜欢。 本示例教你通过使用脚本代码&#xff0c;对Air201模组进行MQTT链接操作。 操作例程包括&#xff1a; MQTT单链接 MQTT多链接 MQTT SSL不带证书链接 MQTT SSL带证书链接 大家可根据自身需求&#xff0c…

ip地址跟路由器有关吗?更换路由器ip地址会变吗

IP地址与路由器之间的关系是一个涉及计算机网络基础知识的话题。在深入探讨这个问题之前&#xff0c;我们首先需要理解IP地址的基本概念以及它在家庭和企业网络中的作用。 IP地址&#xff0c;即互联网协议地址&#xff0c;是分配给网络上的每个设备的数字标签&#xff0c;用于…

CSS综合练习

该综合练习就是为这个静态网页设置CSS样式&#xff0c;使其变成下面的模样 设置CSS样式前&#xff1a; 设置CSS样式后&#xff1a; 其骨架为&#xff1a; <body><div class"qwq"><img src"top.jpg" alt""></div><d…

神经网络基础--什么是神经网络?? 常用激活函数是什么???

前言 本专栏更新神经网络的一些基础知识&#xff1b;案例代码基于pytorch&#xff1b;欢迎收藏 关注&#xff0c; 本人将会持续更新。 神经网络 1、什么是神经网络 人工神经网络&#xff08; Artificial Neural Network&#xff0c; 简写为ANN&#xff09;也简称为神经网络…

《AI大模型对软件开发流程的重塑:变革、优势、挑战与展望》

《AI大模型对软件开发流程的重塑&#xff1a;变革、优势、挑战与展望》 一、传统软件开发流程与模式&#xff08;一&#xff09;传统软件开发流程&#xff08;二&#xff09;传统软件开发模式面临的问题&#xff08;一&#xff09;AI在软件开发中的应用场景&#xff08;二&…

初识C++(上) -- C++的关键字、命名空间、缺省参数以及函数的重载

目录 一、C的关键字&#xff08;C98&#xff09; 二、命名空间 1、命名冲突 2、命名空间 2.1 命名空间的定义 (1). 命名空间定义的例子以及命名空间的嵌套&#xff1a; (2). 同一个工程中允许存在多个相同名称的命名空间,编译器最后会合成同一个命名空间中&#xff1a; 2…

template和span标签的使用

一&#xff1a;template template是模板占位符&#xff0c;可帮助我们包裹元素&#xff0c;而且循环过程当中&#xff0c;template不会被渲染到页面。 <div>ABC</div> <template v-for"(item, index) in 5"><div>{{ index }}</div>&…

Oracle视频基础1.4.4练习

1.4.4 [dbs] 删干净上次创建的bbk ll rm -f *dbf ll rm -f spfilebbk.ora clear ll创建bbk的pfile&#xff0c;准备对应的目录 ll strings spfilewilson.ora | more strings spfilewilson.ora > initbbk.ora :%s/wilson/bbk :%s/*\.//g :wq ll vi initbbk.ora####### 创…

C# 选择导入文件的路径、导出文件的路径

通过C#代码&#xff0c;调出windows风格的文件选择对话框和存储文件对话框。提供界面来选择文件的位置&#xff0c;并将完整路径以字符串形式返回。 1、选择导入文件&#xff0c;获取其路径 C#通过这段代码将弹出一个文件选择对话框&#xff0c;允许用户选择一个文件&#xff…

孤岛的总面积(Dfs C#

卡码网 101题 力扣第 1254. 统计封闭岛屿的数目 也是一样的 差不多是一道题 101. 孤岛的总面积 题目描述 给定一个由 1&#xff08;陆地&#xff09;和 0&#xff08;水&#xff09;组成的矩阵&#xff0c;岛屿指的是由水平或垂直方向上相邻的陆地单元格组成的区域&…

论文解读 P2《Knowledge Graphs Meet Multi-Modal Learning: A Comprehensive Survey》

论文解读系列文章目录 文章目录 论文解读系列文章目录一、图中公式什么意思&#xff1f;二、“早期的基于匹配和密集嵌入相似性的方法&#xff0c;逐步发展到可学习的检索技术和预训练语言模型&#xff08;PLM&#xff09;生成技术”什么意思&#xff1f;三、在从问题&#xff…

http请求响应详解

http介绍 http协议&#xff1a; Http”协议称为是“超文本传输协议”&#xff08;HTTP-Hypertext transfer protocol&#xff09;。它定义了浏览器怎么向万维网服务器请求万维网文档&#xff0c;以及服务器怎么样把文档传送给浏览器。 https协议&#xff1a; 传统的HTTP协议…

mysql5安全审计

安装插件 插件需要严格与数据库版本适配&#xff0c;不然安装过程中会出现问题 解压插件 cd 插件所在路径unzip audit-plugin-mysql-5.7-1.1.7-921-linux-x86_64.zip#查看mysql默认插件目录 mysql> SHOW GLOBAL VARIABLES LIKE plugin_dir;# 将插件移动到mysql默认插件目…

一文解秘Rust如何与Java互操作

本博客所有文章除特别声明外&#xff0c;均采用CC BY-NC-SA 4.0许可协议。转载请注明来自 唯你 使用场景 JAVA 与 Rust 互操作让 Rust 可以背靠 Java 大生态来做更多事情&#xff0c;而 Java 也可以享受 Rust 语言特性的内存安全&#xff0c;所有权机制&#xff0c;无畏并发。…

架构零散知识点

1 数据库 1.1 数据库范式 有一个学生表&#xff0c;主键是学号&#xff0c;含有学生号、学生名、班级、班级名&#xff0c;违反了数据库第几范式&#xff1f; --非主属性不依赖于主键&#xff0c;不满足第二范式 有一个订单表&#xff0c;包含以下字段&#xff1a;订单ID&…

ZISUOJ 2024算法基础公选课练习一(1)

前言、 又是一年算法公选课&#xff0c;与去年不同的是今年学了一些纯C&#xff08;而不是带类的C&#xff09; 一、我的C模板 1.1 模板1 #include <bits/stdc.h> using i64 long long;int main() {std::cin.tie(nullptr)->sync_with_stdio(false);return 0; } 1…