哈夫曼编码
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
南京工程学院
通信工程学院
《信息论与编码》大作业课程名称信息论与编码学生班级电子信息121
学生姓名顾健
实验成绩评定
指导教师签字
年月日
基于C++语言的哈夫曼(Haffman)编码
哈夫曼(Haffman)编码是一种常用的压缩编码方法,是哈夫曼于1952年为压缩文本文件建立的。它的基本原理是按照概率大小顺序排列信源符号,并设法按逆顺序分配码字字长,使编码的码字为可辨识的。哈夫曼码是最佳码。
二进制哈夫曼码的编码步骤如下:
(1) 将q 个信源符号按概率分布)(i s p 的大小,以递减次序排列起来,设q p p p p ≥•••≥≥≥321
(2) 用0和1码符号分别代表概率最小的两个信源符号,并将这两个概率最小的信源符号合并成一个符号,从而得到只包含q-1个符号的新信源,称为S 信源的缩减信源1S 。
(3) 把缩减信源1S 的符号仍按概率大小以递减次序排列,再将最后两个概率最小的符号合并成一个符号,并分别用0和1码符号表示,这样又形成了q-2个符号的缩减信源2S 。
(4) 依此继续下去,直至最后只剩两个符号为止。将这最后两个信源符号分别用0和1码符号表示。然后从最后一级缩减信源开始,向前返回,就得出各信源符号所对应的码符号序列,即对应的码字。
下面举一个具体的Huffman 编码的例子(如图1所示):
信源符号 概率 信源缩减过程 编码 码长
1S 0.4 00 2
2S 0.2 10 2 3S 0.2 11 2 4S 010 3 5S 011 3 图1 Huffman 编码示例
它的平均码长为
)/(2.2305.0315.022.022.024.0)(5
1信源符号码符号=⨯+⨯+⨯+⨯+⨯=∑==i i i l s p L 信息熵为
)/(08.2)log()(-)(5
1信源符号比特=∑==i i i s s p S H 编码效率为
%5.94%1002
.208.2)(=⨯==L S H η 哈夫曼编码方法得到的码并非是唯一的。造成非唯一的原因是:
(1) 任意的,每次对信源缩减时,赋予信源最后两个概率最小的符号,用0和1是可以任意
的,所以可以得到不同的哈夫曼码,但不会影响码字的长度。
(2) 对信源进行缩减时,两个概率最小的符号合并后的概率与其他信源符号的概率相同时,这两者在缩减信源中进行概率排序,其位置放置次序是可以任意的,故会得到不同的哈夫曼码。此时将影响码字的长度,一般将合并的概率放在上面,这样可获得较小的码方差。 算法的实现:
(1) 对于Huffman 编码问题,在构造Huffman 树时,要求能方便地实现从父结点到左右孩子结点的操作,在进行Huffman 编码时,又要求能方便地实现从孩子结点到父结点的操作。因此,设计Huffman 树的结点存储结构为父亲孩子存储结构。
根据数据结构理论可知,二叉数结点的父亲孩子存储结构可用仿真指针实现。另外,每个结点还要有权值域。其元素结构如下:
由Huffman 编码过程可见,从Huffman 树求叶子结点的Huffman 编码实际上是从叶子结点到根结点路径分支的逐个遍历,每经过一个分支就得到一位Huffman 编码值。因此,需要一个数组bit[MaxBit]保存每个叶子结点到根结点路径所对应的Huffman 编码。由于是不等长编码,需要一个数据域len 表示每个Huffman 编码的长度。这样,每个叶子结点的Huffman 编码是从数组bit 的起始位置start 开始到数组结束位置中存放的0到1的序列,data
1) 定义哈夫曼树的结点结构huffnode 。
2) 定义哈夫曼编码的结构huffcode 。
3) 数组初始化。
4) 构造哈夫曼树。
① 构造n 棵只有一个根结点的二叉树,并找出根结点权值最小的两棵树;
② 将找出的两棵树合并为一颗子树。
5) 求各字符的哈夫曼编码。
6) 输出字符的哈夫曼编码。
要求:对任意的符号序列进行哈夫曼编码,并给出编码效率。
哈夫曼编码的c++程序:
/*******************哈夫曼编码
*******************/
#include
#include
#include
#define n 100
#define m 2*n-1
//码结点的存储结构
typedef struct
{
char ch;
char bits[9];
int len;
}CodeNode;
typedef CodeNode HuffmanCode[n+1];
//树结点的存储结构
typedef struct
{
int weight;
int lchild,rchild,parent;
}HTNode;
typedef HTNode HuffmanTree[m+1];
int num;
//挑选权值最小的两个结点
void select(HuffmanTree HT,int k,int &s1,int &s2)
{
int i,j;
int minl=32767;
for(i=1;i<=k;i++)
if(HT[i].weight { j=i; minl=HT[i].weight; } s1=j; minl=32767; for(i=1;i<=k;i++) if(HT[i].weight { j=i; minl=HT[i].weight; } s2=j; } //统计输入字符和串 int jsq(char *s,int cnt[],char str[]) { char *p; int i,j,k=0; int temp[257]; for(i=0;i<257;i++) temp[i]=0; for(p=s;*p!='\0';p++) temp[*p]++; for(i=0,j=0;i<=256;i++) if(temp[i]!=0) {