目录
1.什么叫霍夫曼编码
2.如何手工运算得到霍夫曼编码
3.完整源码
(1)只输出权值
(2)输出树形
霍夫曼编码(英语:Huffman Coding),又译为哈夫曼编码、赫夫曼编码,是一种用于无损数据压缩的熵编码(权编码)算法。由大卫·霍夫曼在1952年发明。
在计算机数据处理中,霍夫曼编码使用变长编码表对源符号(如文件中的一个字母)进行编码,其中变长编码表是通过一种评估来源符号出现机率的方法得到的,出现机率高的字母使用较短的编码,反之出现机率低的则使用较长的编码,这便使编码之后的字符串的平均长度、期望值降低,从而达到无损压缩数据的目的。
例如,在英文中,e的出现机率最高,而z的出现概率则最低。当利用霍夫曼编码对一篇英文进行压缩时,e极有可能用一个比特来表示,而z则可能花去25个比特(不是26)。用普通的表示方法时,每个英文字母均占用一个字节,即8个比特。二者相比,e使用了一般编码的1/8的长度,z则使用了3倍多。倘若我们能实现对于英文中各个字母出现概率的较准确的估算,就可以大幅度提高无损压缩的比例。
霍夫曼树又称最优二叉树,是一种带权路径长度最短的二叉树。所谓树的带权路径长度,就是树中所有的叶结点的权值乘上其到根结点的路径长度(若根结点为0层,叶结点到根结点的路径长度为叶结点的层数)。树的路径长度是从树根到每一结点的路径长度之和。
前缀码:编码的任意前缀不是其他编码
解码结果唯一,编码方式可行
问题:如何求得编码后二进制串总长最短的前缀码?
优先处理低频字符
⚫ 将字符频数从小到大排序 =< , , … , > ( ≤ ≤ ⋯ ≤ )
⚫ 选择两个最小的频数, ,合并为 ′ = +
⚫在 ′ =< ′, , … , > 中重复选择合并过程
#include
#include
#include
using namespace std;
priority_queue,greater > q;
int main()
{
int n;
cin>>n;
int x;
for(int i=0;i>x;
q.push(x);
}
while(q.size()>1)
{
int x,y;
x=q.top();
q.pop();
y=q.top();
q.pop();
q.push(x+y);
}
cout<
#include
#include
#include
#include
#include
#include
using namespace std;
struct node//结构体
{
int sum;//该点权值
node *left;
node *right;
};
node an[10010];
bool cmp1(node a,node b){return a.sumsum>b->sum;
}
};
priority_queue,cmp > q;//优先队列 递增排序
int main()
{
int n;
cin>>n;//建立有n个点的Huffman树
int x;
//(这里如果直接输入值插入队列里面有点bug,得按规律输入,改不出来了QAQ,
// 只好先输入一组数据排序后再插入队列里面)
for(int i=0;i>an[i].sum;
an[i].left=NULL;
an[i].right=NULL;
}
sort(an,an+n,cmp1);
for(int i=0;i1)//按权值从小到大建树
{
node *a;//取两个最小点合并
a=(node*)malloc(sizeof(node));
a->sum=0;
a->left=q.top();
a->sum+=q.top()->sum;
q.pop();
a->right=q.top();
a->sum+=q.top()->sum;
q.pop();
q.push(a);//把新点放入优先队列
//cout<<"push增加成功"< q2;
queue q3;
q2.push(gen);
cout<<"该huffman树形大概为:"<0)
{
if(q2.front()==NULL)
{
q2.pop();
continue;
}
q3.push(q2.front()->left);
q3.push(q2.front()->right);
cout<sum<<" ";
q2.pop();
if(q2.size()==0)
{
while(q3.size()>0)
{
q2.push(q3.front());
q3.pop();
}
cout<sum<