数据压缩与信源编码Huffman编码压缩

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

第一步,我们要对文本的内容进行扫描,统计,并且记录下来,在这里使用 了方法是:对扫描得到的 ASCII 码进行从开始进行匹配,有两种情况:第一,改 码已经出现则,直接让对应的权值 W_weight 增加 1;第二,如果扫描遍历后发 现没有,则码字总类 k 增加 1,将该新的码字赋给新的结构体,权值设为 1。重 复值文件扫描结束。 第二步,需要对其进行 Huffman 树的创立,并且要对其进行编码,生成 Huffman 压缩码。首先,根据 Huffman 二叉树的算法,我们需要先得到权值最小 的两个码字。这里程序中使用了 void Select(HuffmanTree HT,int n,int *s1,int *s2)函数,用最简单的 比较方法就开变了得出,并通过指针参数 s1,s2 传递。得到最小的两个后,我们 通过函数 void HuffmanCoding(HuffmanTree *HT,HuffmanCode *HC,Weight *w,int n) 进行 Huffman 编码实现。 算法思想即为普通的二次扫描编码的方法,详细见程序 的该函数部分的内容和注释。 第三步, 将编好的 Huffman 码写入到压缩文件中,再一次对文件正文进行扫 描,没扫描到一个就用编号的 Huffman 码代替相关的 ASCII 码。在这之前,考虑 到和解码的相对应,在写入到压缩文档之前。需要提供一些信息给解压缩程序, 其中包括, 文本的大小, 用 size 表示, 文本总的总类数目, 用 k 表示, 每种 ASCII 码对应的 Huffman 码,按照 Huffman 树的顺序。 第四部,输出产生相应的文件即可,同时打印出压缩前后的文件的大小,为 计算压缩比提供依据。 (2) Huffman 解码算法程序说明 第一步,读出文件的前部分内容,包括对应的文本的大小,用 size 表示, 文本总的总类数目,用 k 表示,每种 ASCII 码对应的 Huffman 码。然后就可以恢 复出 Huffman 数。这里用到 unsigned int Read()函数和 unsigned int Readk(unsigned int k),这两 个函数可以配合着实现 Huffman 码的读取,详细见程序及其对应的注释。 第二部, 扫描全文, 将之与 Huffman 码进行匹配, 每次匹配均从根节点开始, 知道左右节点没有,这样不会出现重复。扫描至文档结束即可。
//Huffman 编码算法 { int i,m,s1,s2,start,c,f; char *cd; if(n<=1) return; m=2*n-1; 数目 (*HT)=(HuffmanTree)malloc((m+1)*sizeof(HTNode)); //在内存为*HT 分配长度 为 m+1 个 HTNode 结构体大小的连续空间 //初始化 HuffmanTree 前 n 个节点 for(i=1;i<=n;++i) { (*HT)[i].elem=w[i-1].elem; (*HT)[i].m_weight=w[i-1].m_weight; (*HT)[i].parent=(*HT)[i].lchild=(*HT)[i].rchild=0; } //初始化 HuffmanTree 前 n+1 到 m 节点 for(;i<=m;++i) { (*HT)[i].elem='0'; (*HT)[i].m_weight=(*HT)[i].parent=(*HT)[i].lchild=(*HT)[i].rchild=0; } //构造 Huffman for(i=n+1;i<=m;++i) { Select(*HT,i-1,&s1,&s2); //s1,s2 得到的是权 值最小的两个点 (*HT)[s1].parent=i; (*HT)[s2].parent=i; (*HT)[i].lchild=s1; (*HT)[i].rchild=s2; (*HT)[i].m_weight=(*HT)[s1].m_weight+(*HT)[s2].m_weight; } //在内存为*HT 分配长度为 n 个 char 大小的连续空间 (*HC)=(HuffmanCode)malloc(n*sizeof(char*)); cd=(char *)malloc(n*sizeof(char)); //为 cd 分配 n 个 char 占的空间大小 cd[n-1]='\0'; //为每个叶子结点进行编码 for(i=1;i<=n;++i) { start=n-1; // 得到数的节点
//从叶子结点开始向上搜索,如果它是其父结点的左孩子,则其编码 为 0,否则为 1,直到根结点 for(c=i,f=(*HT)[i].parent;f!=0;c=f,f=(*HT)[f].parent) { if((*HT)[f].lchild ==c) cd[--start]='0'; else cd[--start]='1'; } (*HC)[i]=(char *)malloc((n-start)*sizeof(char)); //为每个结点的编码分配 存储空间 strcpy((*HC)[i],&cd[start]);//将结点的编码首地址保存到 HC 中 //printf("%x ",*(*HC)[i]); } //假设编码时正确的 } void Select(HuffmanTree,int,int *,int *); //***************8 向 outfp ****************************** void Write(unsigned int bit) { bits++; chl=(chl<<1)+bit; if(bits==8) { //缓冲区已满,写入 outfp fputc(chl,outfp); //printf("zhigeshi%d \n",chl); bits=0; chl=0; } } //******************* 向 outfp 中 ****************************** void Writek(unsigned int num,unsigned int h) { int *s; unsigned int i,bit; bit =0; s=(int *)malloc((h+2)*sizeof(int)); for(i=1;i<=h;i++) 写 入 k 个 比 特 中 写 入 //选择结点 一 个 比 特
二、 实验内容
(1)编写 Huffman 压缩程序 Huffman_Code 对 abc.txt 进行压缩,压 缩结果存储在 abc_code.txt 中; (2)编写 Huffman 解压缩程序 Huffman_Decode 对*_code.txt 进行解压, 恢复结果存储在*_decode.txt 中; (3)默认码表法 / 两遍扫描的基本方法 / 自适应压缩方法 任选其一。
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <math.h> #include <fcntl.h> #include <io.h> typedef char ** HuffmanCode; //结构体定义区 typedef struct { char elem; unsigned int m_weight; unsigned int parent,lchild,rchild; }HTNode,*HuffmanTree; //Huffman 树对应结点 typedef struct weight { char elem; unsigned int m_weight; }Weight; //符号及其出现次数 //全局变量定义区 int bits; //记录实际比特数,清空缓冲区 char chl; //字节 int lbits; FILE *infp,*outfp; //输入/出文件 //**************************选择出权值最小并且父亲结点的权值为 0 的 2 个结点********************* void Select(HuffmanTree HT,int n,int *s1,int *s2)
六、 程序源代码
/* 程序思路:本程序采用 二次扫描的方法进行编码,首先先扫描一遍,得 到各种 ASCII 字符,并存入 到结构 Weight 里。然后进行 Huffman 编码。本次编码思想主要体现在,每一个 码子“1” “0”得出后 直接当成字节存入写入压缩文件中。 压缩文件头部信息:1.文件总字节数目,单位:byte 2.各种 ASCII的种类数目 3.各种 ASCII 的编码输出 4.正文写入 */
三、 算法流程
(1) 两遍扫描法进行 Huffman 压缩编码算法流程
(2) Huffman 解码算法流程
四、 程序设计说明
(1) 两遍扫描法进行 Huffman 压缩编码算法程序说明 首先, 决定程序好坏优劣以及算法实现难易程度的重要因素便是程序的数据 结构。本程序使用了两个数据结构: typedef struct { char elem; unsigned int m_weight; unsigned int parent,lchild,rchild; }HTNode,*HuffmanTree; typedef struct weight { char elem; unsigned int m_weight; }Weight; 第一个数据结构是为了建立 Huffman 树而用结构体构造的结构体。 其中的成 员包括 ASCII 码的名字 elem,权重 m_weight(有第一次扫描得到的频数决定) , 以及用来建立二叉树的父节点,左右孩子节点。 第二个数据结构是第一扫描统计各个 ASCII 码得到的频数而建立的结构体。 其次是实现算法的函数。
五、 程序压缩性能评价
经过压缩,abc.txt 的大小S1 = 20,370Byte,压缩后的 abc_code 的大小S2 = 12,165Byte。则: 压缩率:r=S 2 =20370 =0。597
1
S
12165
可见,其压缩率并不是特比高。 分析:因为文件大小仅为 20K 左右,经过程序对文件的分析,文件中所含有 的 ASCII 码值得种类为 77 中,Huffman 编码最大码长 l=8(注意,因为存储方法 按字节,所以这里 8bit 就可以) ,在存储 Huffman 编码时浪费 B B=(8-1)*77bit=53.9Byte。 加上 Huffman 编码的算法的限制,可以忍受。 但是,如果文件更长,会发现压缩率会减小(效果会提高) 。但有 Huffman 编码的上限。 解码,经过严格比较,发现完全正确。
数据压缩与信源编码大作业一
----Huffman 编解码实现
一、 实验目的
(1)通过本次实验,加深对 Huffman 编码算法思想的理解,掌握 Huffman 编码的基本规则,熟悉并且理解 Huffman 编码的基本步骤。在此基础上,能够通 过编写 C 语言代码实现 Huffman 编码的编写压缩工作。 (2)通过实现 Huffman 编码压缩工作,进一步进行解码工作,并且用 C 语言实现,以此进一步加深理解。
百度文库
{ int i; (*s1)=(*s2)=0; //初始化 s1 和 s2 for(i=1;i<=n;i++) { if(HT[i].m_weight<HT[(*s2)].m_weight&& HT[i].parent==0 &&(*s2)!=0) { if(HT[i].m_weight<HT[(*s1)].m_weight) 址保存在 s1 中 { (*s2)=(*s1); (*s1)=i; } else (*s2)=i; } if(((*s1)==0||(*s2)==0)&&HT[i].parent==0) 点 { if((*s1)==0) (*s1)=i; else if((*s2)==0) { if(HT[i].m_weight<HT[(*s1)].m_weight) { (*s2)=(*s1); (*s1)=i; } else (*s2)=i; } } } if((*s1)>(*s2)) { i=(*s1); (*s1)=(*s2); (*s2)=i; } return; } //****************************************Huffman 编 码 算 法 *************************** void HuffmanCoding(HuffmanTree *HT,HuffmanCode *HC,Weight *w,int n) //为 s1 和 s2 初始植入结 // 将权值最小的结点地
相关文档
最新文档