当前位置:文档之家› 哈夫曼编码演示

哈夫曼编码演示


//创建并输出编码表 generate_code(root, 0); fout = fopen(“code.txt”, "w"); dump_code(fout); //压缩 fout = fopen(decoded.txt, "w"); encode(fout);
return 0; } 这是我的main函数,为了方便观看做了些 许简省,去掉了关闭文件,清理资源的等 代码行。但仍可以运行。
2
程序介绍
压缩程序
思路: 1.读入文件,统计频率,为出现的每一个字符建立节点,并排成一列 2.将节点转化成哈夫曼树 3.利用哈夫曼树产生编码表文件 4.利用编码将源文件转换成二进制编码表示的文本文件 5.将转码后的文本文件压缩成bin文件
0 1 0 a 0.1 1 b 0.2 c 0.7
产生代码 a: 00 b: 01 c: 1
4
结束感想
本次编写还算成功,虽然调试途中出现了一些大大小小的bug,但是都没有造成很 严重的困扰,可能是因为我采用了老师的框架,绕过了很多陷阱的原因,同时也向 那些自己编写整个程序或是自己不断创新的同学表以敬意。 同时非常高兴的是这是第一次我们能学以致用,编写出能在在生活中得到应用的程 序,这充分体现了一点:科技改善生活。
for(j=0; j<wordnum/8; j++) { character=0; for(i=0; i<8; i++) character += (c = getc(fin)-48) * (int)pow(2,i); fwrite(&character,sizeof(char),1,fout); }
C语言中1个char类型占8bit,在计算机中,也就是8位二进制数,相当 于可以存储0-255大小的十进制数。 所以我们要想把字符串存储转化为二进制存储,只需要将每8位字符串 对应的十进制数计算出来,存入每个char类型。 若最后不足8位,补0至8位即可。
解压缩程序中,只需要将char存储的十进制数通过求余运算即可转化 为二进制数,然后存入字符串即可还原成文本文件,然后再将其解压 缩即可。
2
程序介绍
解压缩程序
思路: 基本思路是找到一个个编码对应的字符还原即可, 步骤如下 1. 将encoded.bin文件转换成二进制编码表示的文 本文件 2. 利用编码表code.txt还原哈夫曼树 3.利用哈夫曼树对文件进行解压缩
主函数: int main() { //初始化 FILE* fout; FILE* fin; root = talloc(); fin = fopen(“code.txt”, "r"); //建树 build_tree(fin); //解码 fin = fopen(encoded.txt, "r"); fout = fopen(“decoded.txt”, "w"); decode(fin, fout); return 0; }
1
总体介绍
可以把哈夫曼编码比作道路优化,原本每个字符占一个char型,也就是8bit,所以 所占空间为 V= 8 * 字符数 (bit) 而编码后,频率高的字符可以用少于8bit表示,而频率低的字符则用多余8bit表示, 这样所占空间为 V= v1*n1+v2*n2+v3*n3+· · · 其中vi代表每个字符所占bit,ni代表字符出现个数,可以证明这样所产生的编码所 占空间是最小的 可以证明这样所得的编码所占空间是最小的。 直观的理解上,就好比城市规划。投入更多的 资金来改善车流量大的道路,而对车流量小的 道路减小投入,这样可使道路资源更充分利用。 在bit的利用上也是如此。
int main(){源自root = pq_pop();
//初始化 struct tnode* p = NULL,* lc, *rc; float freq[255]= {0}; int NCHAR = 255,i = 0; memset(code, 0, sizeof (code)); //统计频率 getfreq(freq); //建立节点队列 for (i = 0; i < NCHAR; i++) if(freq[i]>0) pq_insert(talloc(i, freq[i])); //建立哈夫曼树(删除子节点创建父节点) while(qhead->next!=NULL) { lc = pq_pop(); rc = pq_pop(); p = talloc(0, lc->freq + rc->freq); lc->parent = rc->parent = p; //建立父子关系 p->right = rc; p->left = lc; p->isleaf = 0; pq_insert(p); }
备注:其实不还原哈夫曼树,使用编码表code.txt 读取存储为字符与编码对应的数组或链表,然后 读取encoded.txt,在数组或链表中来找对应编码 还原字符的方法也是可以的,且代码更为简单, 但不如利用哈夫曼树查找还原的效率高。
3
关键问题
按位存储
思路: 按字符串存储的0,1 文件压缩与解压缩是相对容易的,因为可使用 fgetc()等函数读取字符。于是,我们只要在此基础上添加二进制翻译 操作即可。
void generate_code(struct tnode* root, int depth) ——产生编码表 void dump_code(FILE* fp) void encode(FILE* fout) void getfreq(float freq[]) 疑难备注: pq_insert()与pq_pop()两个函数搭配使用,前者用于构建节点队列, 方便遍历节点从而找到最小节点。 后者用于建立哈夫曼树,也就是在建立父节点后在队列中删除那 两个最小的子节点,以免每次找到同样的两个最小节点。 a b c
2
程序介绍
压缩程序
函数: struct tnode* talloc(int symbol, float freq) void pq_insert(struct tnode* p) struct tnode* pq_pop() ——为字符创建节点 ——将节点插入升序排列的队列 ——将队列中第一个(最小频率)节点删除 ——输出编码表 ——压缩文件 ——统计字符频率
哈夫曼编码与文件压缩
——1236003 6120610319 杜嘉诚
内容
1
总体介绍
2
程序介绍
3
关键问题
4
结束感想
1
总体介绍
哈夫曼编码是一种编码方式,经常用于数据压缩。在计算机信息处理中,哈夫 曼编码是一种一致性编码法(又称“熵编码法”),用于数据的无损耗压缩。
它的基本原理是建立一张编码表将原字符(例如某文件的一个符号)进行重新编 码。它是根据每一个源字符出现的概率而建立起来的,这些字符(如字母)出现的 次数越多,其编码的位数就越少。这时的编码之后的字符串的平均期望长度降 低,从而达到无损压缩数据的目的)。 这种方法是由David.A.Huffman发展起来的,故称为哈夫曼编码。
3
关键问题
按位存储
由字符串翻译为二进制: void translatetobin(FILE *fout,FILE *fin,int wordnum) { int j,i,character; unsigned char c;
· · //翻译:一共有总数/8组数据,每组利用a*20+b*21+c*22· 计算后输出即可
谢谢观看
}
3
关键问题
按位存储
由二进制翻译为字符串: Void translatetochar(FILE *fin,FILE *fout) { unsigned char c,d; int i; //翻译:一共有总数/8组数据,每组利用短除法计算后输出即可 while (fread(&c,sizeof(char),1,fin)) { for(i=0;i<8;i++) { fprintf(fout,"%c",d=c%2+48); c=c/2; } } }
相关主题