赫夫曼树赫夫曼编码的创建

news2024/11/15 17:52:01

目录

  • 基础知识点
    • 最优二叉树
    • 如何构造赫夫曼树
    • 赫夫曼编码
    • 编码与压缩文件
  • 代码
    • 结构体设计
    • 创建赫夫曼树
    • 创建构建赫夫曼编码

基础知识点

赫夫曼树又称为最优树,是一种带权路径长短最短的树,有着广泛的应用。

最优二叉树

我们给出路径和路径长度的概念。从树的一个结点到另一个结点之间的分治构成这两个结点之间的路径,路径上的分支数目称作路径长度。树的路径长度是从树根到每一个结点的路径长度之和。完全二叉树就是这种路径长度最短的二叉树。带权路径的长度从结点到树根之间的路径长度域结点上权值的乘积。树的带权路径长度为树中所有叶子结点的带权路径长度之和。
WPL=(W1L1+W2L2+W3L3+…+WnLn)
例如下图:在这里插入图片描述
WPL=24+34+43+92+72+82=80
下图是叶子节点权值相同路径不同的三棵二叉树,计算他们的权值如下:
2*(9+4+5+2)=40
14+22+35+39=50
91+52+43+23=37
我们发现不同路径权值相同,其带权路径长度不同,而最小的便是我们的赫夫曼树。
在这里插入图片描述

如何构造赫夫曼树

赫夫曼最早给出了一个带有一般规律的算法,俗称赫夫曼算法。如下

  • 根据给定的n个权值{w1,w2,……,wn}构成n棵二叉树的集合F={T1,T2……Tn},其中每棵二叉树Ti中只有一个带权为wi的根结点,其左右子树均为空。
  • 在F中选取两棵根节点的权值最小的树作为左右子树构造一棵新的二叉树,且置新的二叉树的根节点的权值为其左,右子树上根节点的权值之和
  • 在F中删除这棵树,同时将新得到的二叉树加入F中。
  • 重复2,3步骤,直到F只含一棵树为止,这棵树便是赫夫曼树。

我们可以进行举例:已知某系统联络中只可能出现8{a,b,c,d,e,f,g,h}种字符,其出现的概率为0.05,0.29,0.07,0.08,0.14,0.23,0.03,0.11,试设计赫夫曼树。
设权w={5,29,7,8,14,23,3,11},n=8,则m=15,按照以上算法可构造以可赫夫曼树。
下图的结点均为叶子节点,我们首先在其中找到权值最小的两个结点,构造一棵而二叉树,比如下面结点我们以做一个左孩子权值为3右孩子权值为5,双亲权值为8的二叉树,然后将权值为8左孩子和右孩子编号为7和1的结点加入下面结点中,就这样选过的不再继续选,将新建立的结点加入其中,每次选出权值最小的两个结点,一直循环下去,直到遍历完所有的结点即可。
在这里插入图片描述
构建完成之后的哈夫曼树:在这里插入图片描述

赫夫曼编码

我们按照以上构造的赫夫曼树化出二叉树如图:在这里插入图片描述

我们根据二叉树的左右孩子进行变码,左为0,右为1,e的变码便是000,h的编码便是001。从根节点依次向下读取即可。

编码与压缩文件

文件压缩流程:

  • 统计文件中所有字符出现的频次
  • 将字符作为节点的值,字符出现的频次作为节点的权,构建哈夫曼树
  • 将哈夫曼树的每个节点的字符与对应的 01 编码作为映射存储到字典中
  • 再次读取文件,将每个字符转化为 01 编码的字符串格式
  • 将这个文件对应的 01 编码字符串转换为真正的比特并写入到文件中,完成压缩

解压流程:

  • 读取压缩文件,将压缩文件转换为 01 的字符串形式
  • 将哈夫曼树的每个节点对应的 01 编码与字符值作为映射存储到字典中(HashMap)
  • 对压缩文件转换成的字符串进行遍历;使用两个指针 i,j,第一个指针 i 指向起始点,第二个指针 j 以 i 所在的位置开始从左向右逐一扫描。如果 i~j 对应的字符串在字典中有匹配的 key,那么就在字典中取出对应的 value 写入到还原的文件中,并更新指针 i 的位置;无匹配的 key 则继续移动 j 指针直至匹配。当 i 移动到字符串最后的位置时,结束遍历,解压完成。

代码

结构体设计

#pragma once
const int n = 8;
const int m = n * 2;
typedef unsigned int WeigthType;
typedef unsigned int NodeType;
typedef struct {
	WeigthType weight;
	NodeType parent, leftchild, rightchild;
}HTNode;
typedef HTNode HuffManTree[m];

typedef struct
{
	char ch;
	char code[n + 1];
}HuffCodeNode;

typedef HuffCodeNode HuffCoding[n + 1];

struct IndexWeigth
{
	int index;
	WeigthType weight;
	operator WeigthType() const { return weight; }
};

创建赫夫曼树

void InitHuffManTree(HuffManTree hft, WeigthType *w) {
	memset(hft,0, sizeof(HuffManTree));
	for (int i = 0; i < n; i++) {
		hft[i+1].weight = w[i];
	}
}
void PrintHuffManTree(HuffManTree hft) {
	for (int i = 1; i <m; ++i) {
		printf("index %3d weight: %3d parent %3d Lchild %3d Rchild %3d\n"
			,i,hft[i].weight,hft[i].parent,hft[i].leftchild,hft[i].rightchild);
	}
}
void CreateHuffManTree(HuffManTree hft) {
	priority_queue<IndexWeigth, vector<IndexWeigth>, std::greater<IndexWeigth> >qu;
	for (int i = 1; i <= n; ++i) {
		qu.push(IndexWeigth{i,hft[i].weight});
	}
	int k = n + 1;
	while (!qu.empty()) {
		if (qu.empty()) break;
		IndexWeigth left = qu.top(); qu.pop();
		if (qu.empty()) break;
		IndexWeigth right = qu.top(); qu.pop();
		hft[k].weight = left.weight + right.weight;
		hft[k].leftchild = left.index;
		hft[k].rightchild = right.index;
		hft[left.index].parent = k;
		hft[right.index].parent = k;
		qu.push(IndexWeigth{k,hft[k].weight});
		k += 1;
	}
}

创建构建赫夫曼编码

void InitHuffManCode(HuffCoding hc, char* ch) {
	memset(hc,0,sizeof(HuffCoding));
	for (int i = 1; i <= n; ++i) {
		hc[i].ch = ch[i-1];
		hc[i].code[0] = '\0';
	}
}
void PrintHuffManCode(HuffCoding hc) {
	for (int i = 1; i <= n; ++i) {
		printf("data: %c => code : %s \n", hc[i].ch, hc[i].code);
	}
}
void CreateHuffManCode(HuffManTree hft, HuffCoding hc) {
	char code[n + 1] = { 0 };
	for (int i = 1; i <= n; ++i) {
		int k = n;
		code[k] = '\0';
		int c = i;
		int pa = hft[c].parent;
		while (pa != 0) {
			code[--k] = hft[pa].leftchild==c?'0' : '1';
			c = pa;
			pa = hft[c].parent;
		}
		strcpy_s(hc[i].code,n,&code[k]);
	}
}

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

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

相关文章

盘点面试常见的设计类算法问题

设计问题也是一种很重要的考察类型&#xff0c;特征是整体难度不大&#xff0c;但是要求结构合理、复用性好、考虑周全&#xff0c;代码规范等等。有些面试官不喜欢烧脑的动态规划等问题&#xff0c;就喜欢设计题&#xff0c;笔者曾经在面试微博和猿辅导都遇到过类似的问题。这…

【操作系统】2.1 进程与线程总结

2.1.1 操作系统之进程的定义、特征、组成、组织 2.1.1 操作系统之进程的定义、特征、组成、组织_StudyWinter的博客-CSDN博客 进程由程序段、数据段、进程控制块&#xff08;PCB&#xff09;三部分组成。 进程是进程实体的运行过程&#xff0c;是系统进行资源分配和资源调度的…

隆化的大米排之首 国稻种芯·中国水稻节:河北承德十大特产

隆化的大米排之首 国稻种芯中国水稻节&#xff1a;河北承德十大特产 中新网河北新闻10月8日电 (张桂芹 王思明) 新闻中国采编网 中国新闻采编网 谋定研究中国智库网 中国农民丰收节国际贸易促进会 国稻种芯中国水稻节 中国三农智库网-功能性农业农业大健康大会报道&#xf…

python基础项目实战-俄罗斯方块

一、俄罗斯方块游戏设计分析: 俄罗斯方块是一款风靡全球,从一开始到现在都一直经久不衰的电脑、手机、掌上游戏机产品,是一款游戏规则简单,但又不缺乏乐趣的简单经典小游戏,上手容易,适用范围广泛,人所共知。俄罗斯方块游戏基本规则是油4个小方块组成的7种不同的规则图形…

DevOps持续部署的关键要素

当有版本通过持续集成流水线进行构建之后&#xff0c;就可以将其部署至某个具体的环境&#xff0c;这就需要自动化部署技术&#xff0c;将这个自动化部署和持续集成流水线连接起来&#xff0c;就可实现持续部署。如图1所示&#xff0c;实现持续部署的前提是至少拥有一条完整的自…

mipi phy理解

MIPI 接口广泛用于摄像头,和显示部分;PHY 属于 MIPI 接口的最底层部分,也就是物理层,直接涉及到物理连线,信号传输等等,要搞清楚 MIPI 的数据传送,那么从 PHY 入手了解,是一个不错的选择;在 PHY 上,只负责定义数据物理层的收发标准; MIPI 的 PHY 分为了 3 种: D-P…

BartForConditionalGeneration的使用细节

输入到 BartForConditionalGeneration 类的各个参数是什么意思&#xff1f; decoder_input_ids 是必须要以 <s> 开头的。这个参数可以自己生成然后传入到模型中&#xff0c;也可以交由代码自己生成&#xff08;一般会根据label右移一位再补0&#xff09; case 1&#x…

ImmunoChemistry艾美捷细胞内GSH测定试剂盒方案

用ImmunoChemistry艾美捷细胞内GSH测定评估细胞内谷胱甘肽水平的变化。这种全细胞谷胱甘肽测定采用专有的硫醇敏感染料ThioBright™ 绿色&#xff0c;以监测游离形式谷胱甘肽&#xff08;即GSH&#xff09;浓度的相对变化。通过流式细胞术分析荧光信号。 谷-胱-甘肽&#xff0c…

​DPDK 高效原因初探

Linux处理Packets主逻辑 系统接受数据包的过程 当网卡收到第一个包时候,通过DMA把这个包发送给接受队列(rx)系统通过中断的方式通知新数据包的到来,同时也需要把数据包传递给内核的buffer(每个包一个buffer,sk_buff struct).一个数据包到来会触发多次的中断&#xff0c;内核处…

.net-----语言集成查询LINQ

语言集成查询LINQ前言相关语言要素初始值设定项匿名类型相关语言要素Lambda表达式扩展方法LINQ的概念和基本操作集成语言查询LINQLINQ查询操作标准查询运算符数据排序数据筛选数据投影数据分组联接运算数据分区限定运算聚合运算集合运算生成运算元素操作串联运算相等运算数据类…

【新知实验室 基于WEB的实时音视频(TRTC)案例搭建】

文章目录1. 实时音视频&#xff08;TRTC&#xff09;1.1 实时音视频(TRTC)概述1.2 实时音视频(TRTC)功能集成1.2.1 含 UI 组件集成方案1.2.2 无 UI 组件集成方案1.3 实时音视频(TRTC)架构2. 使用体验2.1 注册腾讯云2.2 申请实时音视频(TRTC)应用2.3 下载SDK的Demo源码2.4 获取 …

前后端结合解决Excel海量公式计算的性能问题

背景 在数据密集的业务领域&#xff0c;尤其是金融&#xff0c;保险&#xff0c;税务等行业中&#xff0c;经常需要利用Excel模型&#xff0c;来对业务进行分析和处理。例如&#xff1a; 1.金融投资&#xff1a; 根据模型进行估值计算&#xff0c;并对投资风险进行评估&#x…

降本增效这九个月,爱奇艺从“穿越火线”,到“冷静增长”

在互联网行业一致宣称降本、提质、增效的小周期里&#xff0c;爱奇艺已经把这个趋势彻底吃透&#xff0c;展现出成熟的一面。 11月22日美股盘前&#xff0c;爱奇艺发布了2022年第三季度业绩&#xff0c;连续三个季度运营盈利&#xff0c;而且当季净增会员数超千万&#xff0c;…

iwebsec靶场 数据库漏洞通关2-Redis数据库漏洞

iwebsec靶场的redis漏洞为未授权漏洞&#xff0c;如下所示。 一、Redis未授权漏洞原因 那么这个未授权漏洞的原理是什么呢&#xff1f;Redis 默认情况下&#xff0c;会绑定在 0.0.0.0:6379&#xff0c;如果没有进行采用相关的策略&#xff0c;比如添加防火墙规则避免其他非信任…

PreScan快速入门到精通第三十九讲基于车道线识别传感器的车道保持辅助算法Demo讲解

车道保持辅助系统介绍: 什么是车道保持辅助系统? 疲劳和分心是无意中偏离车辆行驶车道线的最常见原因。车道保持辅助系统主动帮助驾驶者将其车辆保持在车道内,避免或者降低事故的发生。 车道保持辅助系统使用一个前置的摄像头,一般安装在车内后视镜附近,用来检测车辆前方…

项目风险管理十大黄金法则!高质量项目管理必杀技!

随着新冠疫情的发生&#xff0c;在这个VUCA时代越来越多企业开始重视风险管理。其实项目风险管理的好处是巨大的&#xff0c;如果您以积极的方式处理不确定的项目事件&#xff0c;则可能赚很多钱或提前拿到现金流。结果是您可以最大程度地减少项目威胁的影响并抓住发生的机会。…

野火FPGA强化(1):串口

文章目录第31讲&#xff1a;串口RS232串口数据接收模块&#xff1a;Uart_rx串口数据发送模块&#xff1a;Uart_tx底层模块&#xff1a;rs232第32讲&#xff1a;使用SignalTap II嵌入式逻辑分析仪在线调试第33讲&#xff1a;串口RS485key_filterwater_ledbreath_ledled_ctrluart…

Linux 内存之vmstat

文章目录前言一、vmstat简介1.1 processes1.2 memory1.3 block IO1.4 System1.5 cpu activity二、使用步骤2.1 vmstat -a2.2 vmstat -f2.3 vmstat -m2.4 vmstat -s2.5 vmstat -d/D三、vmstat 数据来源参考资料前言 NAMEvmstat - Report virtual memory statisticsvmstat 报告有…

Gang Scheduling Performance Benefits for Fine-Grain Synchronization

Gang Scheduling Performance Benefits for Fine-Grain Synchronization 题目 什么是 gang secheduling &#xff1f; 组调度&#xff0c;要么一组全部执行&#xff0c;要么都不执行什么是 fine-grain 同步 &#xff1f;细粒度同步 CSDN 博客 摘要 gang scheduling, where …

SSM框架的基本整合

整合SSM框架要做哪些事情&#xff1a; SpringMVC: pom web.xml a. 前端调度器servlet b. 编码过滤器filter c. 支持rest的过滤器springmvc.xml a. 扫描controller包 b. 添加 c. 视图解析器 d. 静态资源解析添加控制器类… Spring:web.xml a. 监听器&#xff08;在启动web容器时…