霍夫曼编码及解码(简单实现)

article/2025/9/24 15:59:52

霍夫曼树

霍夫曼树又称最优二叉树,是一种带权路径长度最短的二叉树。

所谓树的带权路径长度,就是树中所有的叶结点的权值乘上其到根结点的路径长度(若根结点为0层,叶结点到根结点的路径长度为叶结点的层数)。

树的路径长度 WPL 是从树根到每一结点的路径长度之和,记为

WPL= \sum_{i=1}^{n}\left (W_{i}\times L_{i} \right )

N个权值Wi(i=1,2,...n)构成一棵有N个叶结点的二叉树,相应的叶结点的路径长度为Li(i=1,2,...n)。可以证明霍夫曼树的WPL是最小的。

假设有n个权值,则构造出的哈夫曼树有n个叶子节点.n个权值记为{w1,w2,w3...wn},哈夫曼树的构造过程为:

  1. 将w1,w2,w3...wn看成具有n棵树的森林,每棵树仅有一个节点。
  2. 从森林中,选取两棵根节点权值最小的树,两棵树分别作为左子树与右子树,构建一棵新树。新树的权值等于左右子树权值之和。
  3. 从森林中删除两棵权值最小的树,将构建完成后的新树加入森林中。
  4. 重复2、3步骤,直到森林只剩一棵树为止。这棵树便是哈夫曼树。

 霍夫曼编码

从根节点到每一个叶子节点的路径上,左分支记为0,右分支记为1,将这些0与1连起来即为叶子节点的哈夫曼编码。

霍夫曼编码,对于出现频率越高的字符(也即权值越大),其编码越短。这便使编码之后的字符串的平均长度、期望值降低,从而达到无损压缩数据的目的。

由此得到的德霍夫曼编码为前缀码,即任何一个字符的编码都不能是其他字符编码的前缀。

根据此特性,通过对编码前几位与字符编码对比,匹配不成功则增加匹配字符的长度,匹配成功则对编码下几位进行匹配,可得到相应解码。

 完整代码

 本次的代码只实现输入字符串后,对本字符串进行霍夫曼编码解码。 

#include<iostream>
#include<string>
#include<list>
#include<algorithm>
#include<fstream>
using namespace std;class node
{public:node *left;node *right;string code;		//编码char data;int value;			//权值node(){left=NULL;right=NULL;value=0;}
};
struct cmp						//函数对象 ,用于list的sort函数
{bool operator()(const node * x, const node* y ){return x-> value < y-> value;}
};int getnode(char data,int value,list<node*> &res)
{node *temp=new node;						//每个数据生成一个结点temp->data=data;temp->value=value;res.push_back(temp);return 0;
}int getnewnode(list<node*> &res)		//取两个权值最小的结点生成新的结点
{node *left=new node;				//最小的取为左子树left=res.front();res.pop_front() ;node *right=new node;				//第二小的取为右子树right=res.front();res.pop_front() ;node *cur=new node;		//创建新节点,连接左右子树cur->value=left->value+right->value;cur->left=left;cur->right=right;res.push_back(cur);return 0;
}void nodecode(node* cur,list<node*> &cod)	//为每个叶子结点进行编码
{if(cur->left!=NULL){cur->left->code="0"+cur->code;nodecode(cur->left,cod);}if(cur->right!=NULL){cur->right->code="1"+cur->code;nodecode(cur->right,cod);}if(cur->left==NULL&&cur->right==NULL){reverse(cur->code.begin(),cur->code.end());cod.push_back(cur);							//每个叶子结点加到list中cout<<cur->data<<":"<<cur->code<<endl;}
}void Hofmanntreecode (node* cur,list<node*> &res) //霍夫曼树编码
{cur->left->code="0";cur->right->code="1";nodecode(cur->left,res);nodecode(cur->right,res);
}string Hofmannencode(int fre[128],string a ,list<node*> &res)		//霍夫曼编码,参数:26个字母出现次数,目标字符串,霍夫曼树结点list
{int count=0;				//有效字符数 for(int i=0; i<128; i++)		//字符生成结点{if(fre[i]!=0){getnode(char(i),fre[i],res);count++;}}for(int i=0; i<count-1; i++)		//选取权值最小的两个生成新结点{res.sort(cmp());getnewnode(res);}node *cur=new node;				//为每个叶子结点编码cur=res.front();res.clear();Hofmanntreecode(cur,res);string code[128];for(list<node*>::iterator it=res.begin(); it!=res.end(); it++)	//得到每个字符的编码 {code[(**it).data]=(**it).code;}string result;for(int i=0; i<a.length(); i++)			//进行编码 {result+=code[a[i]];}return result;}string getstring(string yourstring, int pos1,  int pos2 )	//字符串切片,得到字符串从pos1到pos2位置的字符串,不包括pos2
{string result;for(int i=pos1; i<pos2; i++){result+=yourstring[i];}return result;
}string Hofmanndecode(string result,string code[128])	//霍夫曼解码,参数:26个字母编码
{string decode;int pos=0;int max=1;for(int i=0; i<128; i++){if(max<code[i].length())max=code[i].length();}while(pos<result.length()){for(int i=0; i<128; i++)				//每几个编码与字母的编码匹配{for(int x=1; x<=max; x++)			//有x个编码一起匹配,知道超出字母最长的编码或者匹配到{if(getstring(result,pos,pos+x)==code[i]){pos+=x;					//移动x个位置decode+=char(i);					//进行解码 break;}}}}return decode;}int main(void)
{list<node*> res;string yourstr;getline(cin,yourstr);int fre[128];for(int i=0; i<128; i++)				//初始化{fre[i]=0;}for(int i=0; i<yourstr.length(); i++)		//统计每个字母出现的次数{fre[yourstr[i]]++;}string result;result=Hofmannencode(fre,yourstr,res);			//霍夫曼编码,参数:26个字母出现次数,目标字符串,霍夫曼树结点liststring code[128];while(!res.empty()){code[res.front()->data]=res.front()->code;res.pop_front();}string decode;decode=Hofmanndecode(result,code);			//霍夫曼解码,参数:26个字母编码cout<<" text :"<<yourstr<<endl;cout<<"encode:"<<result<<endl;cout<<"decode:"<<decode;
}

 

 输入:

I love you, but you don't love me!

 输出:

 :00
l:0100
t:0101
v:0110
y:0111
!:10000
':10001
,:10010
I:10011
b:10100
d:10101
m:10110
n:10111
o:110
e:1110
u:1111
 text :I love you, but you don't love me!
encode:10011000100110011011100001111101111100100010100111101010001111101111001010111010111100010101000100110011011100010110111010000
decode:I love you, but you don't love me! 


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

相关文章

霍夫曼树和霍夫曼编码原理

一、哈夫曼树的概念和定义 什么是哈夫曼树&#xff1f; 让我们先举一个例子。 判定树&#xff1a; 在很多问题的处理过程中&#xff0c;需要进行大量的条件判断&#xff0c;这些判断结构的设计直接影响着程序的执行效率。例如&#xff0c;编制一个程序&#xff0c;将百分制转换…

学习笔记--霍夫曼树与霍夫曼编码解码

先摘一下百科的说法 “哈夫曼编码(Huffman Coding)&#xff0c;又称霍夫曼编码&#xff0c;是一种编码方式&#xff0c;哈夫曼编码是可变字长编码(VLC)的一种。Huffman于1952年提出一种编码方法&#xff0c;该方法完全依据字符出现概率来构造异字头的平均长度最短的码字&#x…

霍夫曼编码的matlab实现

霍夫曼编码的原理已经有很优秀的介绍博客了&#xff0c;给出现频率高的灰度级分配更短的码字无非就是利用数学中逆序乘积和最小的原理&#xff0c;具体的原理介绍我就不再赘述了。这里给大家分享一下我个人早先实现的霍夫曼编码matlab程序。废话不多说&#xff0c;直接上代码&a…

霍夫曼树和霍夫曼编码以及霍夫曼编码的应用

文章目录 霍夫曼树介绍1.1霍夫曼树的定义1.2霍夫曼树的几个概念1.3构建霍夫曼树的过程1.4代码实现霍夫曼树 霍夫曼编码介绍什么是霍夫曼编码通信领域的应用 字符串压缩1.构造霍夫曼树2.生成赫夫曼树对应的赫夫曼编码表3.通过生成的赫夫曼编码表&#xff0c;返回一个赫夫曼编码 …

霍夫曼编码判断

霍夫曼编码判断 (算法学习) 霍夫曼编码一定是前缀编码&#xff0c;即&#xff0c;没有任何一个编码是另一个编码的前缀。 此外&#xff0c;还需要明白霍夫曼编码构建的树中只有度为0和2的结点&#xff0c;不存在度为1的结点。这与玩全二叉树是不一样的概念&#xff0c;玩全二…

霍夫曼编码和LZ编码

文章目录 一、霍夫曼编码1.概念及编码步骤2.霍夫曼编码例题分析 二、LZ编码1.概念及编码步骤2.LZ编码例题分析 一、霍夫曼编码 1.概念及编码步骤 霍夫曼编码是定长到变长编码&#xff0c;其概率高的符号映射成较短的二进制序列&#xff0c;概率低的符号映射成较长的二进制序列…

[基础知识] 霍夫曼编码

来源&#xff1a;Reducible内容整理&#xff1a;张志宇该视频详细讲解了霍夫曼编码提出的思路历程。 目录 故事背景思路历程 通信系统示意衡量信息量编码和熵的关系香农-冯诺编码霍夫曼的改进 故事背景 1951 年&#xff0c;麻省理工学院的一名研究生 David Huffman 在 Robert F…

数据结构【二】:霍夫曼编码

霍夫曼编码&#xff08;Huffman Coding&#xff09;是可变长编码&#xff08;VLC&#xff09;的一种。本质上使用变长编码表对源符号进行编码&#xff0c;通过评估源符号出现概率的方法进行分类&#xff0c;将出现几率较高的源字符使用较短的编码&#xff0c;出现几率较低的源字…

霍夫曼树——霍夫曼编码

霍夫曼编码 基本介绍 霍夫曼编码是一种编码方式&#xff0c;属于一种程序算法霍夫曼编码是霍夫曼树在通讯领域的经典应用之一霍夫曼编码广泛用于数据文件的压缩&#xff0c;压缩率通常在20% 到90%&#xff0c;通常数据的重复率越高&#xff0c;那么压缩率就越高霍夫曼编码是可…

【数据结构】图解霍夫曼编码,看了就能懂

今天来给大家普及一下霍夫曼编码&#xff08;Huffman Coding&#xff09;&#xff0c;一种用于无损数据压缩的熵编码算法&#xff0c;由美国计算机科学家大卫霍夫曼在 1952 年提出——这么专业的解释&#xff0c;不用问&#xff0c;来自维基百科了。 说实话&#xff0c;很早之前…

霍夫曼编码原理以及代码实现

霍夫曼编码压缩能够实现对于自然语言文件空间大幅压缩。对于普通的文本文件字符&#xff0c;简单起见&#xff0c;如果字符为ASCII&#xff0c;则文本中的每个字符使用7bit来表示&#xff0c;如果文本中有大量的重复相同序列&#xff0c;使用ASCII编码来保存存储会造成大量的空…

霍夫曼编码(huffman coding) (java实现)

文章目录 一、浅谈赫夫曼编码二、获取赫夫曼编码1.获取字符出现的次数2.创建赫夫曼树3.指定编码 三、代码实现1.指定编码代码2.完整代码 总结 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一、浅谈赫夫曼编码 赫夫曼编码(Huffman Coding)&#xff0c…

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

一、简介 霍夫曼树常处理符号编写工作。根据整组数据中符号出现的频率高低&#xff0c;决定如何给符号编码。如果符号出现的频率越高&#xff0c;则给符号的码越短&#xff0c;相反符号的号码越长。 相关术语 路径&#xff1a;从书中一个节点到另一个节点之间的分支构成这两个…

霍夫曼编码

霍夫曼在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…