ImageVerifierCode 换一换
格式:DOCX , 页数:21 ,大小:25.83KB ,
资源ID:5817135      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/5817135.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(信息论程序 半字节 哈弗曼 重复码编译码.docx)为本站会员(b****6)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

信息论程序 半字节 哈弗曼 重复码编译码.docx

1、信息论程序 半字节 哈弗曼 重复码编译码实验一 英文半字节压缩编码技术实验二 Huffman编码 实验三 重复码编译码方法 实验一 英文半字节压缩编码技术一、实验目的 1、理解信源编码的作用和目的,掌握数据压缩的基本思想;2、掌握数据压缩中常用的比特流操作办法;3、掌握英文半字节压缩编码技术。二、实验内容 通过C语言编程,实现对一般英文文本文件的半字节压缩编码与译码程序,并观察编码、译码结果以及压缩效果。三、实验原理 对于一个通信系统来说,信息传输的有效性、可靠性、安全性和认证性是人们的主要目标。其中,信息传输的有效性指的是尽可能的使用较短的时间和较少的设备等资源来传送尽可能多的信息,而这一目

2、的主要是通过信源编码这个环节来实现的。 虽然有许许多多不同的信源编码方法,但总的说来,信源编码主要是通过减少或消除信源的剩余度来提高传输效率的。而且,有时人们为了追求更高的传输效率,在满足实际需求的情况下,还允许在编译码过程中存在一定程度的失真,这就是所谓的有损压缩。当然,针对不同的应用要求,可以选择不同的压缩编码办法,为了方便理解和实现,针对一般的英文文本,可以设计一种半字节压缩编码方法来实现数据的压缩。(一)有损处理 在一般英文文本中,除了大、小写英文字母外,还有多种不同的标点符号。为了达到在不影响文章大意的前提下,尽可能的减少需编码的符号数,以提高信息传输效率的目的,可采取这样的处理方法

3、:1) 所有的英文字母不区分大、小写(如:将所有的大写英文字母变成小写字母);2) 保留标点符号:“,”、“。”、“?”“:”和“ ”;3) 将“!”和“;”变为“。”,其他符号全部变成“ ”。这样,原来的英文文本就变成了一个新的文本,该文本全部由26个英文字母和“,”、“。”、“?”、“:”以及“ ”这31种符号组成,而且,文章的大意并没有发生大的变化。可以认为这种失真是在允许的失真范围之内的。当然,为了简化操作,上面的第一步也可省略。虽然这样会使输出文件中既有大写字符,又有小写字符,但只需在后面的编码操作时将大、小写等同处理,则同样达到了不区分大小写的目的。(二)数据压缩 在计算机中,文本

4、文件中的每个符号都是由8位的ASCII码所构成,共有256种取值的可能。既然经过上述有损处理后文件中只存在31种不同的符号,所以在压缩编码过程中只需对31种符号进行编码,就可以大大压缩文本文件的数据量。考虑到各字母以及符号出现的概率,并考虑码字的可分离性,可以采取以下的编码方法来进行数据的压缩:1) 对于概率最大的15个符号分别编以“0000”“1110”的码字:符号 码字 符号 码字 符号 码字 符号 码字空格 0000 e 0100 l 1000 s 1100a 0001 f 0101 n 1001 t 1101c 0010 h 0110 o 1010 u 1110d 0011 i 011

5、1 r 1011 2) 对于其余的16个符号分别编以“1111 0000”“1111 1111”的码字。符号 码字 符号 码字 符号 码字 符号 码字, 1111 0000 b 1111 0100 m 1111 1000 w 1111 1100. 1111 0001 g 1111 0101 p 1111 1001 x 1111 1101? 1111 0010 j 1111 0110 q 1111 1010 y 1111 1110: 1111 0011 k 1111 0111 v 1111 1011 z 1111 1111这样,一些最经常出现的符号从原来的8bit变为4bit,达到了数据压缩的目

6、的。从表中可以看出,后16个符号的码字中前4比特均为“1111”,因此可先向编码文件输出前4比特,然后再输出后4比特。这样的好处是:不论是前15种符号还是后16种符号,都可执行同一种输出操作(输出4比特),只是对于后16种符号是连续执行两次而已。 (三)译码译码过程是编码的逆过程,解码后得到由这31种符号所组成的文本文件。由于后16个符号的码字中前4比特均为“1111”,因此可设计译码过程为:每次读取4bit。若不为“1111”,则根据此次读取的4bit译为相应的前15个符号之一;若为“1111”,则再次读取4bit,并根据后4bit译为相应的后16个符号之一。这样,不论是前15种符号还是后1

7、6种符号的译码,都可执行同一种读取操作(读取4比特),只是对于后16种符号是连续执行两次而已。(四)半字节操作 在计算机中,所有对数据的操作(不论是数据的存储还是对文件的读写)都是以字节(8bit)为基本单位的,而我们的编码与解码都是以半个字节(4bti)为单位的,因此需要运用位操作来进行数据的控制:1)编码过程中,执行的操作是每次输出4比特。由于每次向输出文件的写入是以字节(8bit)为单位的,因此可定义一个缓存变量来存储每次输出的4比特数据。只有当缓存中的有效数据凑足8bit(1字节)时才执行一次向输出文件的写入操作。这里需要注意的是,如果待编码文件中所有符号的码长之和不是8的整数倍时,就

8、会出现缓存中剩余4比特有效数据不能输出(因为不能凑够满字节)的情况。这时可以在后面补4比特“0000”(即为空格),使其能够输出到输出文件中。2)译码过程中,执行的操作是每次读取4bit。由于每次向输入文件的读取是以字节(8bit)为单位的,故需将每次读取的8bit(1字节)存入缓存,然后使用位操作依次读取其前后各4比特。四、实验步骤1、编写有损处理程序,在不影响文章大意的基础上对英文文本文件进行有损处理,减少需编码的符号数,产生待编码文件;2、编写半字节编码程序,对待编码文件进行半字节压缩编码,并计算压缩比,观察压缩效果;3、编写半字节解码程序,对压缩后的文件进行解码,并与压缩前的文件进行比

9、较。五、实验环境1、计算机;2、Visual C+编程环境。六、实验报告要求1、格式与内容应符合实验报告标准;2、对程序设计的思路以及具体设计步骤应详细说明,并附上相应的程序流程图;3、对程序设计中发生的问题以及解决的办法要加以叙述与总结;4、附上所设计的程序清单,并对关键部分进行说明。/*编码程序*/#include#includechar EditTxt(char a) if(a=A & a=a & a=z) if(a=; | a=!) a=.; / 将!和;变为。 else if(a!= & a!=: & a!=? & a!=, & a!=.) a= ; return a;int Get

10、Id(char *p,char a) int i; for(i=0;i31;i+) if(pi=a) break; return i;void main() FILE *rfp,*wfp; int i, flag; unsigned char ch,term=0; char a31= ,a,c,d,e,f,h,i,l,n, o,r,s,t,u,.,?,:,b, g,j,k,m,p,q,v,w,x,y,z; if(rfp=fopen(file.txt,r)=NULL) printf(Cannot open infile!n); exit(0); if(wfp=fopen(file2.txt,w)

11、=NULL) printf(Cannot open midfile!n); exit(0); flag=1; ch=getc(rfp); while(!feof(rfp) ch=EditTxt(ch); i=GetId(a,ch); if(i=14) if(flag=0) /缓冲未满 putc(term|i,wfp); flag=1; else /缓冲已满 term=i*16; flag=0; else if(flag=0) /缓冲未满 putc(term|15,wfp); term=(i-15)*16; flag=0; else /缓冲已满 putc(240|(i-15),wfp);flag

12、=1; ch=getc(rfp); if(flag=0) putc(term,wfp); fclose(rfp); fclose(wfp);/*解码程序*/#include#includevoid main() FILE *rfp,*wfp; int flag; unsigned char ch,high,low; char a31= ,a,c,d,e,f,h,i,l,n, o,r,s,t,u,.,?,:,b, g,j,k,m,p,q,v,w,x,y,z; if(rfp=fopen(file2.txt,r)=NULL) printf(Cannot open file!n); exit(0);

13、if(wfp=fopen(file3.txt,w)=NULL) printf(Cannot open file!n); exit(0); flag=1; ch=getc(rfp); while(!feof(rfp) high=ch4; low=ch&15; if(flag=0) putc(ahigh+15,wfp); flag=1; else if(high=15) flag=0; else putc(ahigh,wfp); flag=1; if(flag=0) putc(alow+15,wfp); flag=1; else if(low=15) flag=0; else putc(alow,

14、wfp); flag=1; ch=getc(rfp); fclose(rfp); fclose(wfp); 实验二 Huffman编码一、实验目的1、熟练掌握Huffman编码过程;2、掌握C语言递归程序的设计和调试技术;3、掌握C语言中的动态分配内存技术。二、试验内容根据输入的信源符号数及相应的概率分布,使用C语言编写Huffman编码程序,从而输出每个信源符号所对应的码字。三、实验原理在众多的无失真信道编码技术中,Huffman编码是一种有效的获得最佳码的编码技术。它能够充分利用短码,大幅度降低码字的平均码长,从而获得较高的编码效率,在保证码字的可分离性的同时,有效的提高了通信系统的有效性

15、。也正是由于Huffman编码技术的优越性,目前在有关信源编码的许多领域中,Huffman编码作为一项基本技术,得到了极为广泛的应用。(一)Huffman编码方法由于目前数字通信中一般都使用二进制符号,因此二进制的Huffman编码技术最为普遍,其编码步骤如下:1、将信源符号按概率从大到小进行排列;2、给两个概率最小的信源符号各分配一个码元“0”和“1”,然后将这两个信源符号合并成一个新符号,并用这两个最小的概率之和作为新符号的概率,结果得到一个只有(n-1)个信源符号的新信源(假设原来所需编码的符号数为n),称为信源的第一次缩减信源S1;3、将缩减信源S1的符号仍按概率从大到小的顺序进行排列

16、,重复步骤2,得到只含(n-2)个符号的缩减信源S2;4、重复上述步骤,直至缩减信源只剩两个符号为止,此时所剩两个符号的概率之和必为1,将这两个符号各分配一个码元“0”和“1”后,从最后一级缩减信源开始,依编码路径向前返回,就得到各信源符号所对应的Huffman码字。(二)方差最小的Huffman码字缩减信源时,若合并后的新符号概率与其他符号的概率相等,从编码方法上来讲,这几个符号的次序可任意排列,编出的码字都是正确的,但不同的编法得到的码字不同,码字长度也不尽相同,从而码长的方差也会不同。若码长的方差较小,则意味着码长变化较小,各个码长都比较接近于平均码长,这样对于信息传输的实现,特别是对传

17、输有实时性要求的时候,会带来很大的便利,因此也就更好一些。为了得到方差最小的Huffman码字,在对缩减信源按概率从大到小重新排列时,应使合并后的新符号尽可能地排在靠前的位置,这样可使合并后的新符号重复编码次数减少,使短码得到充分利用,降低码长的方差。(三)递归算法实现Huffman编码由于在Huffman编码过程中,每次都是对减少一个符号数的缩减信源进行同样的操作排序与合并,且最终的码字是按照编码路径逆序返回而得到,因此可利用递归的思想实现Huffman的编码程序。假设对n个符号、概率为pi的信源进行Huffman编码,则递归实现算法的主要思想可简单描述为:procedure Huffman

18、(n,pi) if n = = 2 then 对两个符号各分配一个码元“0”和“1”; else 降序排序; 合并符号,并得到新的概率分布pi; Huffman(n-1, pi); 对被合并的两个符号各分配一个码元“0”和“1”;end procedure(四)动态分配内存由于本程序设计要求根据所输入的信源符号数与概率分布进行Huffman编码,在输入之前并不确定所要编码的信源符号数,而且编得的码字长度也不能确定,因此对各符号以及相应码字的存储使用固定长度的数组显然不太合适,而在C语言中使用动态分配内存技术则可以根据需要灵活分配存储空间,从而有效的解决这个问题。C语言中常用的动态内存管理函数有

19、以下四个:1、函数malloc这是给指针动态分配内存的通用函数。它的原型是:void * malloc (size_t nbytes)其中nbytes 是我们想要给指针分配的内存字节数。这个函数返回一个void*类型的指针,因此我们需要用类型转换(type cast)来把它转换成目标指针所需要的数据类型,例如:char * ronny;ronny = (char *) malloc (10);这个例子将一个指向10个字节可用空间的指针赋给ronny。当我们想给一组除char 以外的类型(不是1字节长度的)的数值分配内存的时候,我们需要用元素数乘以每个元素的长度来确定所需内存的大小:int *

20、bobby;bobby = (int *) malloc (5 * sizeof(int);这一小段代码将一个指向可存储5个int型整数的内存块的指针赋给bobby,它的实际长度可能是 2,4或更多字节数,取决于程序是在什么操作系统下被编译的。2、函数calloccalloc 与malloc 在操作上非常相似,他们主要的区别是在原型上:void * calloc (size_t nelements, size_t size)可见它接收2个参数而不是1个,这两个参数相乘被用来计算所需内存块的总长度。通常第一个参数(nelements)是元素的个数,第二个参数 (size) 被用来表示每个元素的长

21、度。例如,我们可以像下面这样用calloc定义bobby:int * bobby;bobby = (int *) calloc (5, sizeof(int);malloc 和calloc的另一点不同在于calloc 会将所有的元素初始化为0。,而malloc 只管分配内存,并不能对所得的内存进行初始化,所以得到的一片新内存中,其值将是随机的。3、函数realloc它被用来改变已经被分配给一个指针的内存的长度。其原型为:void * realloc (void * pointer, size_t size)参数pointer 用来传递一个已经被分配内存的指针或一个空指针,而参数size 用来指

22、明新的内存长度。这个函数给指针分配size 字节的内存。这个函数可能需要改变内存块的地址以便能够分配足够的内存来满足新的长度要求。在这种情况下,指针当前所指的内存中的数据内容将会被拷贝到新的地址中,以保证现存数据不会丢失,然后返回新的指针地址。如果新的内存尺寸不能够被满足,函数将会返回一个空指针,但原来参数中的指针pointer 及其内容保持不变。4、函数 free这个函数用来释放被前面malloc, calloc 或realloc所分配的内存块:void free (void * pointer);注意:如果忘记释放动态分配地内存,程序就会在结束时出现内存泄漏的问题。(五)程序设计问题1、数

23、据存储根据实验要求,我们要根据输入的信源符号数及相应的概率分布输出每个信源符号所对应的码字,因此需要定义一个记录信源符号序号的数组,一个记录相应符号概率的数组,一个记录各符号码字的二维数组,且各数组的长度应根据输入的信源符号数决定。2、排序从Huffman算法流程来看,第一次排序和对缩减信源的排序略有不同。对缩减信源的排序是在基本有序的情况下进行排序的,也就是说,除了合并符号以外,其他的符号已经是降序排列的,因此只需将合并的符号插入到相应的位置即可。而且为了得到方差最小的Huffman码字,应使合并后的新符号尽可能地排在靠前的位置。对于第一次排序则没有这样的条件与要求。也正是为此,我们可以在上

24、述的递归算法中将这两种排序分开:(主程序)第一次排序;procedure Huffman(n,pi) if n = = 2 then 对两个符号各分配一个码元“0”和“1”; else 合并符号,并得到新的概率分布pi; 缩减信源的排序; Huffman(n-1, pi); 对被合并的两个符号各分配一个码元“0”和“1”;end procedure由于对信源符号的描述有三个数组:序号、概率以及码字,因此排序中的每次改变都需对这三个数组同时进行相应的变动。3、递归编码在递归算法中,每次递归都需要对参与合并的两个符号分配码元。由于对信源符号的描述由数组完成,因此在逐级返回时只是返回指向数组的指针,

25、而其中元素的值不能返回。为了在每次返回上一级递归时找到这两个符号,则需要在每次递归时记录下这两个符号的序号,以便返回时能正确的对这两个符号分配码元。四、实验步骤1、使用C语言编写Huffman编码程序;2、输入几种信源的符号数及其概率,将程序输出的码字与手动计算的码字进行比较,验证程序的正确性。 五、实验环境1、计算机;2、Visual C+编程环境。六、实验报告要求1、格式与内容应符合实验报告标准;2、对程序设计的思路以及具体设计步骤应详细说明,并附上相应的程序流程图;3、对程序设计中发生的问题以及解决的办法要加以叙述与总结;4、附上所设计的程序清单,并对关键部分进行说明。#include

26、#includestdlib.hstruct NODE float w; int parent,lchild,rchild;void Huffman(int *ID,struct NODE *HT,int m,int n) HT2*n-m.w=HTIDm-1.w+HTIDm-2.w; HTIDm-1.parent=2*n-m; HTIDm-2.parent=2*n-m; HT2*n-m.lchild=IDm-1; HT2*n-m.rchild=IDm-2; HT2*n-m.parent=-1; IDm-2=2*n-m;void Select(int *ID,struct NODE *HT,in

27、t m) int k,t; t=IDm-1; for(k=0;km-1;k+) if(HTIDk.w=HTIDm-1.w) IDm-1=IDk; IDk=t; t=IDm-1; void main() struct NODE *HT; int *ID,*CODE; char *ch; int n,i,j,t,m,b,f; float sum; printf(Please enter the number of the symbols:n); scanf(%d,&n); ID=(int *)malloc(sizeof(int)*n); ch=(char *)malloc(sizeof(char)

28、*n); CODE=(int *)malloc(sizeof(int)*n); HT=(struct NODE*)malloc(sizeof(struct NODE)*(2*n-1); printf(Please enter the symbolsn); for(i=0;in;i+) fflush(stdin); scanf(%c,&chi); printf(Please enter the probabilityn); sum=0; for(i=0;in;i+) fflush(stdin); scanf(%f,&HTi.w); HTi.parent=-1; HTi.lchild=-1; HTi.rchild=-1; sum+=HTi.w; if(sum!=1) printf(ERRORn); exit(-1); for(i=0;in;i+) /首次对码元进行排序 t=0; for(j=0;jn;j+) if(HTi.wj) t+; IDt=i;

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1