霍夫曼树:霍夫曼编码(Huffman Tree:Huffman Coding)

article/2025/9/24 16:47:08

一、简介

        霍夫曼树常处理符号编写工作。根据整组数据中符号出现的频率高低,决定如何给符号编码。如果符号出现的频率越高,则给符号的码越短,相反符号的号码越长。

相关术语

路径:从书中一个节点到另一个节点之间的分支构成这两个节点的路径。

路径长度:即路径上有多少个分支。

树的路径长度:从树根到每一个节点的路径长度之和。

带权路径长度:从根节点到叶子节点的路程长度与该节点权值的积。

树的带权路径长度:树中所有带权叶子节点的路径长度之和。

        霍夫曼编码就是再霍夫曼树上进行实现的。

        从树根开始,从待译电文中逐个取码。若编码为0,就往左走;编码为1,就往右走,一旦到达了叶子节点,就是译出了一个字符;在从根出发,直到电文结束。 

图1

T:00 ;:00 A:10 C:110 S:111

参考图1:

电文是{CAS;CAT;SAT;AT}

编码就是11010111011101000011111000011000

电文如果是1101000

译文就是CAT

        假设我们要给一个英文单字"FORGET"进行霍夫曼编码。

演算过程

(一)进行编码前,要先创建一个霍夫曼树。

⒈将每个英文字母依照出现频率由小排到大,最小在左,如Fig.1;

⒉每个字母都代表一个终端节点(叶节点),比较F.O.R.G.E.T六个字母中每个字母的出现频率,将最小的两个字母频率相加合成一个新的节点。如Fig.2所示,发现FO的频率最小,故相加2+3=5;

⒊比较5.R.G.E.T,发现RG的频率最小,故相加4+4=8;

⒋比较5.8.E.T,发现5E的频率最小,故相加5+5=10;

⒌比较8.10.T,发现8T的频率最小,故相加8+7=15;

⒍最后剩10.15,没有可以比较的对象,相加10+15=25。

最后产生的树状图就是霍夫曼树。

(二)进行编码

1.给霍夫曼树的所有左链接'0'与右链接'1';

2.从树根至树叶依序记录所有字母的编码。

二、代码实现 

#include <bits/stdc++.h>
using namespace std;
//霍夫曼树的结构
typedef struct
{//叶子结点权值unsigned int weight;//指向双亲,和孩子结点的指针unsigned int parent;unsigned int lChild;unsigned int rChild;
}Node,*HuffmanTree;
//动态分配数组,存储哈夫曼编码
typedef char *HuffmanCode;
//选择两个parent为0,且weight最小的结点s1和s2的方法实现
//n 为叶子结点的总数,s1和 s2两个指针参数指向要选取出来的两个权值最小的结点
void select(HuffmanTree *huffmanTree,int n,int *s1,int *s2)
{//标记iint i=0;//记录最小权值int min;//遍历全部结点,找出单节点for(i=1; i<=n; i++){//如果此结点的父亲没有,那么把结点号赋值给 min,跳出循环if((*huffmanTree)[i].parent==0){min=i;break;}}//继续遍历全部结点,找出权值最小的单节点for(i=1; i<=n; i++){//如果此结点的父亲为空,则进入 ifif((*huffmanTree)[i].parent==0){//如果此结点的权值比 min 结点的权值小,那么更新 min 结点,否则就是最开始的 minif((*huffmanTree)[i].weight<(*huffmanTree)[min].weight){min=i;}}}//找到了最小权值的结点,s1指向*s1=min;//遍历全部结点for(i=1; i<=n; i++){//找出下一个单节点,且没有被 s1指向,那么i 赋值给 min,跳出循环if((*huffmanTree)[i].parent==0&&i!=(*s1)){min=i;break;}}//继续遍历全部结点,找到权值最小的那一个for(i=1; i<=n; i++){if((*huffmanTree)[i].parent==0&&i!=(*s1)){//如果此结点的权值比 min 结点的权值小,那么更新 min 结点,否则就是最开始的 minif((*huffmanTree)[i].weight<(*huffmanTree)[min].weight){min=i;}}}//s2指针指向第二个权值最小的叶子结点*s2=min;
}
//创建霍夫曼树并求霍夫曼编码的算法如下,w数组存放已知的n个权值
void createHuffmanTree(HuffmanTree *huffmanTree, int w[], int n)
{//m为哈夫曼树总共的结点数,n为叶子结点数int m=2*n-1;//s1和s2为两个当前结点里,要选取的最小权值的结点int s1;int s2;//标记int i;//创建哈夫曼树的结点所需的空间,m+1,代表其中包含一个头结点*huffmanTree=(HuffmanTree)malloc((m+1)*sizeof(Node));//1--n号存放叶子结点,初始化叶子结点,结构数组来初始化每个叶子结点,初始的时候看做一个个单个结点的二叉树for(i=1; i<=n; i++){//其中叶子结点的权值是 w[n]数组来保存(*huffmanTree)[i].weight=w[i];//初始化叶子结点(单个结点二叉树)的孩子和双亲,单个结点,也就是没有孩子和双亲,==0(*huffmanTree)[i].lChild=0;(*huffmanTree)[i].parent=0;(*huffmanTree)[i].rChild=0;}//非叶子结点的初始化for(i=n+1; i<=m; i++){(*huffmanTree)[i].weight=0;(*huffmanTree)[i].lChild=0;(*huffmanTree)[i].parent=0;(*huffmanTree)[i].rChild=0;}printf("\n HuffmanTree: \n");//创建非叶子结点,建哈夫曼树for(i=n+1; i<=m; i++){//在(*huffmanTree)[1]~(*huffmanTree)[i-1]的范围内选择两个parent为0//且weight最小的结点,其序号分别赋值给s1、s2select(huffmanTree,i-1,&s1,&s2);//选出的两个权值最小的叶子结点,组成一个新的二叉树,根为 i 结点(*huffmanTree)[s1].parent=i;(*huffmanTree)[s2].parent=i;(*huffmanTree)[i].lChild=s1;(*huffmanTree)[i].rChild=s2;//新的结点i的权值(*huffmanTree)[i].weight=(*huffmanTree)[s1].weight + (*huffmanTree)[s2].weight;printf("%d (%d, %d)\n",(*huffmanTree)[i].weight,(*huffmanTree)[s1].weight,(*huffmanTree)[s2].weight);}   printf("\n");
}
//哈夫曼树建立完毕,从 n 个叶子结点到根,逆向求每个叶子结点对应的哈夫曼编码
void creatHuffmanCode(HuffmanTree *huffmanTree, HuffmanCode *huffmanCode, int n)
{//指示biaojiint i;//编码的起始指针int start;//指向当前结点的父节点int p;//遍历 n 个叶子结点的指示标记 cunsigned int c;//分配n个编码的头指针huffmanCode=(HuffmanCode *)malloc((n+1) * sizeof(char *));//分配求当前编码的工作空间char *cd = (char *)malloc(n * sizeof(char));//从右向左逐位存放编码,首先存放编码结束符cd[n-1] = '\0';//求n个叶子结点对应的哈夫曼编码for(i = 1; i <= n; i++){//初始化编码起始指针start = n - 1;//从叶子到根结点求编码for(c = i, p = (*huffmanTree)[i].parent; p != 0; c = p, p = (*huffmanTree)[p].parent){if( (*huffmanTree)[p].lChild == c){//从右到左的顺序编码入数组内cd[--start] = '0';  //左分支标0}else{cd[--start] = '1';  //右分支标1}}// end of for//为第i个编码分配空间huffmanCode[i] = (char *)malloc((n - start) * sizeof(char));strcpy(huffmanCode[i], &cd[start]);}free(cd);//打印编码序列for(i=1; i<=n; i++){printf("HuffmanCode of %3d is %s\n", (*huffmanTree)[i].weight, huffmanCode[i]);}printf("\n");
}
int main()
{HuffmanTree HT;HuffmanCode HC;int *w,i,n,wei,m;printf("\nn = " );scanf("%d",&n);w=(int *)malloc((n+1)*sizeof(int));printf("\ninput the %d element's weight:\n",n);for(i=1; i<=n; i++){printf("%d: ",i);fflush(stdin);scanf("%d",&wei);w[i]=wei;}createHuffmanTree(&HT, w, n);creatHuffmanCode(&HT,&HC,n);return 0;
}

参考文献:

【C++】霍夫曼树与编码(原理详细&代码注释)_米莱虾的博客-CSDN博客哈夫曼树(最优二叉树)❥分享大一所做笔记❥知识点解析WPL:树的所有叶结点的带权路径长度之和,称为树的带权路径长度表示为WPL不带权值的话,完全(满)二叉树的路径长度最小最优二叉树 != 最佳判定树权值相等或不存在的话,最优二叉树就是完全二叉树代码(注释详细)#include <bits/stdc++.h>using namespace std;//haffman 树的结构ty...https://blog.csdn.net/Luoxiaobaia/article/details/122460555以上就是本文的全部内容啦!感谢阅读!


http://chatgpt.dhexx.cn/article/K7ArosG6.shtml

相关文章

霍夫曼编码

霍夫曼在1952年提出了霍夫曼编码&#xff0c;霍夫曼编码是一种无损的统计编码方法&#xff0c;利用信息符号概率分布特性来改编字长进行编码。适用于多元独立信源。霍夫曼编码对于出现概率大的信息符号用字长小的符号表示&#xff0c;对于出现概率小的信息用字长大的符号代替。…

霍夫曼(Huffman)编码算法详解之C语言版

一、Huffman编码 霍夫曼(Huffman)树是一类带权路径长度最短的二叉树树。Huffman树的一个非常重要的应用就是进行Huffman编码以得到0-1码流进行快速传输。 在电报收发等数据通讯中&#xff0c;常需要将传送的文字转换成由二进制字符0、1组成的字符串来传输。为了使收发的速度提…

哈夫曼编码

哈夫曼编码 概念前缀码的二叉树及权值哈夫曼编码的设计思想 实例伪代码 概念 哈夫曼编码是一种字符编码方式&#xff0c;是可变长编码的一种&#xff0c;1952年提出&#xff0c;依据字符在文件中出现的频率来建立一个用0,1串表示各字符&#xff0c;使平均每个字符的码长最短的…

图像处理—霍夫曼编码

图像压缩编码是专门研究图像数据压缩的技术&#xff0c;就是尽量减少表示数据图像所需要的数据量。 本章主要介绍图像压缩编码的基础知识&#xff0c;重点讲解常用的图像压缩编码方法&#xff0c;如霍夫曼编码、香农编码、算术编码、行程编码和预测编码及编码方法的MATLAB实现&…

哈夫曼编码(理解)

基础理解 什么是哈夫曼树&#xff08;Huffman Tree&#xff09; 给定N个带权值的叶子节点&#xff0c;如何构造出一个带权路径最小的二叉树&#xff1f; 在数据结构理论中&#xff0c;哈夫曼树又称为最优树&#xff0c;相关的知识点还有哈弗曼编码等。在正式介绍哈夫曼树之前…

学弟学妹们,学会霍夫曼编码后,再也不用担心网络带宽了!

CSDN 的学弟学妹们&#xff0c;大家好&#xff0c;我是沉默王二。 今天来给大家普及一下霍夫曼编码&#xff08;Huffman Coding&#xff09;&#xff0c;一种用于无损数据压缩的熵编码算法&#xff0c;由美国计算机科学家大卫霍夫曼在 1952 年提出——这么专业的解释&#xff…

哈夫曼编码详解

一&#xff1a;基本介绍 哈夫曼编码也翻译为 赫夫曼编码(Huffman Coding)&#xff0c;又称霍夫曼编码&#xff0c;是一种编码方式, 属于一种程序算法 赫夫曼编码是赫哈夫曼树在电讯通信中的经典的应用之一。 赫夫曼编码广泛地用于数据文件压缩。其压缩率通常在20%&#xff5…

赫夫曼编码

一 基本介绍 1 赫夫曼编码也翻译为哈夫曼编码(Huffman Coding)&#xff0c;又称霍夫曼编码&#xff0c;是一种编码方式, 属于一种程序算法。 2 赫夫曼编码是赫哈夫曼树在电讯通信中的经典的应用之一。 3 赫夫曼编码广泛地用于数据文件压缩。 其压缩率通常在20%&#xff5e;9…

哈夫曼编码(Huffman Coding)原理详解

哈夫曼编码 哈夫曼编码&#xff0c;又称为哈夫曼编码&#xff08;Huffman Coding&#xff09; 是一种可变长编码&#xff08; VLC, variable length coding)&#xff09;方式&#xff0c;比起定长编码的 ASCII 编码来说&#xff0c;哈夫曼编码能节省很多的空间&#xff0c;因…

霍夫曼编码详解

本专栏包含信息论与编码的核心知识&#xff0c;按知识点组织&#xff0c;可作为教学或学习的参考。markdown版本已归档至【Github仓库&#xff1a;information-theory】&#xff0c;需要的朋友们自取。或者公众号【AIShareLab】回复 信息论 也可获取。 文章目录 霍夫曼编码最佳…

霍夫曼编码(Huffman Coding)

霍夫曼编码(Huffman Coding)是一种编码方法,霍夫曼编码是可变字长编码(VLC)的一种。 霍夫曼编码使用变长编码表对源符号(如文件中的一个字母)进行编码,其中变长编码表是通过一种评估来源符号出现机率的方法得到的,出现机率高的字母使用较短的编码,反之出现机率低的则使用…

Typecho 博客美化

以前用typecho博客&#xff0c;现在学生服务器到期了&#xff0c;先记录到csdn上&#xff0c;以后工作有钱了&#xff0c;再租个服务器写博客:) 代码高亮 https://www.typechodev.com/plugin/482.html 天气功能 使用心知天气带的插件就可以轻松实现了。 https://www.seniverse…

Hexo博客之博客美化

https://lqgjava.github.io/2019/08/24/Hexo博客之博客美化/ 只需阅读这一篇文章&#xff0c;就可以让你的博客变得丰富多彩&#xff0c;有添加卡通人物&#xff0c;添加鼠标点击爱心&#xff0c;添加鼠标指针样式 添加彩色滚动变换、添加背景音乐、添加动态彩带等&#xff0…

CSDN博客美化

排列博客分类 管理博客-分类专栏下修改 双击分类名称&#xff0c;即可编辑&#xff0c;输入“#”“空格”“分类名称”可将一级分类改成二级分类。 显示的效果 分类图标设置 编辑-设置图标&#xff0c;可以这里找阿里素材库 效果图

【CSDN】CSDN博客美化教程

一、效果 二、MarkDown简明教程 MarkDown简明教程 三、摘要 添加摘要&#xff0c;增加可读性。 PS. 其实&#xff0c;可以根据深度学习算法&#xff0c;自动生成摘要。 四、自定义博客栏目 五、修改皮肤

博客美化作业详细教程

博客美化作业 第一步 下载作业资源 第二步 在文件夹内打开下载资源 单击后缀为HTML文件的网页文件&#xff0c;右击用编译器打开 这些软件都可以&#xff08;除了紫色的&#xff09; 第三步 准备工作 首先让我们重新看下作业要求&#xff1a; 必须使用“类选择器”来美化网…

【全网最全的博客美化系列教程】04.访客量统计的实现

全网最全的博客美化系列教程相关文章目录 【全网最全的博客美化系列教程】01.添加Github项目链接 【全网最全的博客美化系列教程】02.添加QQ交谈链接 【全网最全的博客美化系列教程】03.给博客添加一只萌萌哒的小仓鼠 【全网最全的博客美化系列教程】04.访客量统计的实现 【全网…

Hexo博客美化之——IP签名图一网打尽

love421个人博客地址&#xff1a;https://www.makedreamsir.xyz IP签名图可以实时显示来访者的坐标&#xff0c;IP地址&#xff0c;操作系统&#xff0c;浏览器等等。 使用方法&#xff1a;将下面生成的链接插入到合适的位置即可。 项目原地址&#xff1a;点我打开 原作者博…

Web前端:博客美化:一、模板美化

1、选用模板simplememory 2、写css放在 这些会覆盖掉原来的css样式 我是在网上找的css代码二次加工的 : &#xff09; /*1、针对simplememory的修改*/ #google_ad_c1, #google_ad_c2 {display:none;} .syntaxhighlighter a, .syntaxhighlighter div, .syntaxhighlighter code, …

Hexo博客之主题美化

据说 NexT 是使用最多的Hexo主题,原因当然是比较漂亮啦!这个项目托管于github上,你可以fork一下,贡献代码。NexT官网上面给出了详细的主题配置过程,这里只是我的博客使用的一些配置以及NexT网站上配置中需要补充的部分。如果你是从头开始配置,请参考NexT官网。这篇文章介…