整理哈夫曼编码汉明编码.docx
《整理哈夫曼编码汉明编码.docx》由会员分享,可在线阅读,更多相关《整理哈夫曼编码汉明编码.docx(16页珍藏版)》请在冰豆网上搜索。
整理哈夫曼编码汉明编码
(完整)哈夫曼编码_汉明编码
编辑整理:
尊敬的读者朋友们:
这里是精品文档编辑中心,本文档内容是由我和我的同事精心编辑整理后发布的,发布之前我们对文中内容进行仔细校对,但是难免会有疏漏的地方,但是任然希望((完整)哈夫曼编码_汉明编码)的内容能够给您的工作和学习带来便利。
同时也真诚的希望收到您的建议和反馈,这将是我们进步的源泉,前进的动力。
本文可编辑可修改,如果觉得对您有帮助请收藏以便随时查阅,最后祝您生活愉快业绩进步,以下为(完整)哈夫曼编码_汉明编码的全部内容。
1课题描述
信息论理论基础的建立,一般来说开始与香农(C.E。
Shannon)在研究通信系统时所发表的论文。
信息论是在信息可以度量的基础上,对如何有效、可靠的传递信息进行研究的科学,它涉及信息亮度、信息特性、信息传输速率、信道容量、干扰对信息传输的影响等方面的知识。
通常把上述范围的信息论称为狭义信息论,又因为它的创始人是香农,故又称为香农信息论。
广义信息论则包含通信的全部统计问题的研究,除了香农信息论之外,还包括信号设计、噪声理论、信号的检测与估值等。
当信息在传输、存储和处理的过程中,不可避免的要受到噪声或其他无用信号的干扰时,信息理论会为可靠、有效的从数据中提取信息提供必要的根据和方法。
因此必须研究噪声和干扰的性质以及它们与信息本质上的差别,噪声与干扰往往具有某种统计规律的随机特性,信息则具有一定的概率特性,如度量信息量的熵值就是概率性质的。
信息论、概率轮、随机过程和数理统计学是信息论应用的基础和工具。
信息论主要研究如何提高信息系统的可靠性、有效性、保密性和认证性,以使信息系统最优化.所谓可靠性高就是要使信源发出的消息经过信道传输以后,尽可能准确的、不失真的再现在接收端;而所谓有效性高,就是经济效果好,即用尽可能少的资源和尽可能少的设备来传送一定数量的信息;所谓保密性就是隐蔽和保护通信系统中传送的信息,使它只能被授权接受者获取,而不能被未授权者接受和理解;而认证性是指接受者能正确的判断所接受的消息的正确性,验证消息的完整性,而不是接收伪造的和被修改的信息。
2信源编码的相关介绍
信源编码分为无失真编码和限失真编码。
一般称无失真信源编码定理为第一极限定理,限失真信源编码为第三极限定理。
由于信源符号之间存在分布不均匀和相关性,使得信源存在冗余度,信源编码的主要任务是减少冗余,提高编码效率。
具体说,就是针对信源输出符号序列的统计特性,寻找一定的方法把信源输出符号序列变换为最短码字序列的方法。
信源编码的基本途径有两个:
使序列中的各个符号尽可能相互独立,即解除相关性;使编码中各个符号出现的概率尽可能相等,即概率均匀化.
信源编码的基础是信息论中的两个编码定理:
无失真编码定理和限失真编码定理,前者是可逆编码的基础。
可逆是指当信源符号转换成代码后,可从代码无失真的恢复原信源符号。
无失真编码或可逆编码只适用于离散信源。
对于连续信源,编成代码后就无法无失真的恢复原来的连续值,因为后者的取值可以有无限多个。
3哈夫曼编码
3。
1哈夫曼编码算法
算法步骤如下:
1)将信源消息符号按照其出现的概率大小依次排列为
2)取两个概率最小的字母分别配以0和1这两个码元,并将这两个概率相加作为一个新字母的概率,与未分配的二进制符号的字母重新排队;
3)对重新排列后的两个概率最小的符号重复步骤2)的过程;
4)不断继续上述操作,直到最后两个符号配以0和1为止;
5)从最后一级开始,向前返回得到各个信源符号所对应的码元序列,即相应的码字。
3.2哈夫曼编码特点
哈夫曼编码(HuffmanCoding)是一种用于无损数据压缩的熵编码算法,是可变长编码的一种。
由于经过哈夫曼编码所编成的码是具有唯一码性质的即时码,即各个相异字元所编出的哈夫曼码都不相同,解码时能够看到编码就立即解出原码
。
总结得哈夫曼编码具有以下特点:
1)编出来的码都是异字头码,保证了编码的唯一可译性;
2)由于编码长度可变,哈夫曼编码与还原耗时很长;;
3)由于编码过程中0,1的指定是任意的,所以哈夫曼编码的结果不唯一;
4)哈夫曼编码不同的结果平均码长都相同.
4哈夫曼编码的c语言程序实现
4.1程序设计
流程图:
全部代码:
#include#include#include
typedefunsignedcharU8;
typedefunsignedshortU16;
typedefunsignedlongU32;
//定义哈夫曼树的结构体
typedefstructHuffmanNode
{
doubleprob;
structHuffmanNode*left;
structHuffmanNode*right;
}huffmancode;
voidInit(U32*,double**);
huffmancode*Encode(double*,U32);
huffmancode*CreateBinaryTree(huffmancode**,int);
voidPrint(huffmancode*,char*);
voidDeleteBinaryTree(huffmancode*);
voidDeleteBinaryTree(huffmancode*pHuffman)
{
if(pHuffman—>left!
=NULL)
DeleteBinaryTree(pHuffman-〉left);
if(pHuffman-〉right!
=NULL)
DeleteBinaryTree(pHuffman-〉right);
free(pHuffman);
return;
}
//输出结果:
给定值转换为哈夫曼编码
voidPrint(huffmancode*pHuffman,char*code)
{
intnumChild=0;
intstrLen=strlen(code);
char*nextCode=(char*)malloc(strLen+2);
if(pHuffman—〉left!
=NULL)
{
numChild++;
strcpy(nextCode,code);
nextCode[strLen]=’1';
nextCode[strLen+1]='\0’;
Print(pHuffman—〉left,nextCode);
}
if(pHuffman-〉right!
=NULL)
{
numChild++;
strcpy(nextCode,code);
nextCode[strLen]='0’;
nextCode[strLen+1]='\0';
Print(pHuffman—>right,nextCode);
}
if(numChild==0)
{
printf(”%lf哈夫曼编码:
%s\n",pHuffman->prob,code);
}
free(nextCode);
return;
}
huffmancode*Encode(double*p,U32n)
{
U32i;
huffmancode*pRes;
huffmancode**ppHuffman;
ppHuffman=(huffmancode**)malloc(sizeof(huffmancode*)*n);
for(i=0;i{
ppHuffman[i]=(huffmancode*)malloc(sizeof(huffmancode));
ppHuffman[i]-〉prob=p[i];
ppHuffman[i]->left=NULL;
ppHuffman[i]-〉right=NULL;
}
pRes=CreateBinaryTree(ppHuffman,n);
free(ppHuffman);
returnpRes;
}
huffmancode*CreateBinaryTree(huffmancode**ppHuffman,intn)
{
inti;
intmin1=0,min2=1;/*min1huffmancode*tmp,*pRes;
pRes=(huffmancode*)malloc(sizeof(huffmancode));
if(ppHuffman[0]-〉prob>ppHuffman[1]—>prob)
min1=1,min2=0;
for(i=2;i〈n;i++)
{
if(ppHuffman[i]->prob〈ppHuffman[min2]->prob)
{
if(ppHuffman[i]-〉prob{
min2=min1;
min1=i;
}
else
{
min2=i;
}
}
}
pRes->prob=ppHuffman[min1]—〉prob+ppHuffman[min2]-〉prob;
pRes-〉left=ppHuffman[min1];
pRes-〉right=ppHuffman[min2];
if(min1==n—1)
ppHuffman[min2]=pRes;
elseif(min2==n-1)
ppHuffman[min1]=pRes;
else
{
ppHuffman[min1]=pRes;
ppHuffman[min2]=ppHuffman[n—1];
}
if(n!
=2)
pRes=CreateBinaryTree(ppHuffman,n-1);
returnpRes;
}
voidInit(U32*n,double**pp)
{
inti;
*n=7;
floata[7];
*pp=(double*)malloc(sizeof(double)*(*n));
for(i=0;i<*n;i++)
{
scanf("%f”,&a[i]);
(*pp)[i]=a[i];
}
return;
}
voidmain()
{
U32n;
double*p;
huffmancode*pHuffman;
Init(&n,&p);
pHuffman=Encode(p,n);
Print(pHuffman,”");
DeleteBinaryTree(pHuffman);
}
4.2运行结果
5汉明编码
5.1汉明编码算法
通用算法:
1)从1开始给数字的数据位(从左到右)标上序号:
1,2,3,4,5等;
2)将这些数据位的位置序号换成二进制:
1,10,11,100,101等;
3)数据位的位置序号中所有为二的幂次方的位是校验位;
4)所有其他位置的数据位是数据位;
5)每一位的数据包含在特定的两个或两个以上的较验位中,这些校验位取决于这些数据位的位置数值的二进制表示:
(1)校验位1覆盖所有数据位位置序号的二进制表示倒数第一位是1的数据;
(2)校验位2覆盖所有数据位位置序号的二进制表示倒数第二位是1的数据;
(3)校验位4覆盖所有数据位位置序号的二进制表示倒数第三位是1的数据;
……
即所有校验位覆盖数据位置和该校验位位置的二进制相与的值不为0的值.
5.2汉明编码特点
汉明编码是一种性能良好的码,它是在纠错编码的实践中较早发现的一类具有单个纠错能力的纠错码,在通信和计算机工程中都有应用.汉明码利用奇偶检验位的概念,通过在数据位后面增加一些比特验证数据的有效性。
奇偶校验是一种添加一个奇偶位用来指示之前的数据中包含有奇数还是偶数个1的检验方式。
利用一个以上的校验位,汉明码不仅可以验证数据是否有效,还可以在数据出错的情况下指明出错位置。
6汉明编码的C++程序实现
6。
1程序设计
流程图:
全部源代码:
#include
#include〈math.h〉
voidhanming()
{
inti,n,k=2;
inth[20];
for(i=0;i<20;i++)
h[i]=0;
printf(”请输入要转换的有效位的位数:
\n");
scanf("%d”,&n);
while(pow(2,k)k++;
printf("请输入要转换的有效码字:
\n”);
for(i=1;i<=n+k;i++){
if(i!
=1&&i!
=2&&i!
=4&&i!
=8)
scanf(”%d",&h[i]);
}
h[1]=(h[3]+h[5]+h[7]+h[9]+h[11]+h[13]+h[15])%2;
h[2]=(h[3]+h[6]+h[7]+h[10]+h[11]+h[14]+h[15])%2;
h[4]=(h[5]+h[6]+h[7]+h[12]+h[13]+h[14]+h[15])%2;
h[8]=(h[9]+h[10]+h[11]+h[12]+h[13]+h[14]+h[15])%2;
for(i=1;i<=n+k;i++)
printf(”%d",&h[i]);
}
intjiaoyan(inta[],intn)
{
inti,p1,p2,p4,p8,m;
inth[20];
for(i=0;ih[i+1]=a[i];
for(i=n+1;i〈20;i++)
h[i]=0;
if(n==3){
//k=2;
p1=(h[1]+h[3])%2;
p2=(h[2]+h[3])%2;
m=2*p2+p1;
returnm;
}
if(n>=5&&n〈=7){
//k=3;
p1=(h[1]+h[3]+h[5]+h[7])%2;
p2=(h[2]+h[3]+h[6]+h[7])%2;
p4=(h[4]+h[5]+h[6]+h[7])%2;
m=4*p4+2*p2+p1;
returnm;
}
if(n>=9&&n〈=15){
//k=4;
p1=(h[1]+h[3]+h[5]+h[7]+h[9]+h[11]+h[13]+h[15])%2;
p2=(h[2]+h[3]+h[6]+h[7]+h[10]+h[11]+h[14]+h[15])%2;
p4=(h[4]+h[5]+h[6]+h[7]+h[12]+h[13]+h[14]+h[15])%2;
p8=(h[8]+h[9]+h[10]+h[11]+h[12]+h[13]+h[14]+h[15])%2;
m=8*p8+4*p4+2*p2+p1;
returnm;
}
else{
printf(”查错出错!
”);
return—1;
}
}
//主函数
intmain()
{
hanming();
intcoco;
inti,n,m,h[20];
printf("\n请输入要查错的码字的位数:
\n”);
scanf(”%d”,&n);
printf(”请输入要查错的码字:
\n”);
for(i=0;iscanf("%d”,&h[i]);
m=jiaoyan(h,n);
if(m==0)
printf("码字没有错误”);
if(m!
=0)
printf(”错误的位数是:
%d\n",m);
return0;
}
6.2运行结果
总结
在这一学期的信息论学习中我们在老师的带领下下学习了很多种编码方式,有信源编码也有信道编码。
虽然老师讲课很认真卖力,我自己平时也有认真完成作业,考试那一周也将书看了两三遍,但我对书上所讲的种种编码方式仍然没有很深的认识。
直到完成了这为期一周的信息论课程设计,我才真正对信源编码这些编码方式有了一些深入的了解.对于这次我选择的这两个编码我还是有一定的了解的,然而在代码的编辑过程中还是状况百出.最终也还是在网上参考了很多的子良才将作业圆满完成了的.敲过一遍完整地代码之后,我对哈夫曼编码和汉明编码的整个过程都已经十分清楚了,而不像之前只是从书本上学知识,虽然懂了,却不通透。
纸上得来终觉浅,绝知此事要躬行。
要想真正掌握一个知识,唯有自己亲自动手实践一次才能将知识点的各个细节都了解清楚,也只有自己动手了我们才能将知识深深的刻进脑子里.在今后的学习中,我会更加注重培养自己动手实践的能力。
参考文献
[1]王俊平,李加彦。
谈谈哈夫曼编码[J]。
中小企业管理与科技旬刊,2009,(6):
258-258.
[2]曹雪虹,张棕橙.信息论与编码[N]。
北京:
清华大学出版社,2009。
[3]龚尚福,贾鹏涛.C/C++语言程序设计.西安:
西安电子科技大学出版社,2012。