信息论实验报告.docx

上传人:b****1 文档编号:20123956 上传时间:2023-04-25 格式:DOCX 页数:63 大小:419KB
下载 相关 举报
信息论实验报告.docx_第1页
第1页 / 共63页
信息论实验报告.docx_第2页
第2页 / 共63页
信息论实验报告.docx_第3页
第3页 / 共63页
信息论实验报告.docx_第4页
第4页 / 共63页
信息论实验报告.docx_第5页
第5页 / 共63页
点击查看更多>>
下载资源
资源描述

信息论实验报告.docx

《信息论实验报告.docx》由会员分享,可在线阅读,更多相关《信息论实验报告.docx(63页珍藏版)》请在冰豆网上搜索。

信息论实验报告.docx

信息论实验报告

信息论实验

实验一

*哈夫曼编码(HuffmanCoding)是一种编码方式,哈夫曼编码是可变字长编码(VLC)的一种。

Huffman于1952年提出一种编码方法,该方法完全依据字符出现概率来构造异字头的平均长度最短的码字,有时称之为最佳编码,一般叫作Huffman编码。

实验目的:

利用程序实现哈夫曼编码,以加深对哈夫曼编码的理解,并锻炼编程能力。

实验分析:

哈夫曼编码步骤:

一、对给定的n个权值{W1,W2,W3,...,Wi,...,Wn}构成n棵二叉树的初始集合F={T1,T2,T3,...,Ti,...,Tn},其中每棵二叉树Ti中只有一个权值为Wi的根结点,它的左右子树均为空。

(为方便在计算机上实现算法,一般还要求以Ti的权值Wi的升序排列。

二、在F中选取两棵根结点权值最小的树作为新构造的二叉树的左右子树,新二叉树的根结点的权值为其左右子树的根结点的权值之和。

三、从F中删除这两棵树,并把这棵新的二叉树同样以升序排列加入到集合F中。

四、重复二和三两步,直到集合F中只有一棵二叉树为止。

简易的理解就是,假如我有A,B,C,D,E五个字符,出现的频率(即权值)分别为5,4,3,2,1,那么我们第一步先取两个最小权值作为左右子树构造一个新树,即取1,2构成新树,其结点为1+2=3,如图:

虚线为新生成的结点,第二步再把新生成的权值为3的结点放到剩下的集合中,所以集合变成{5,4,3,3},再根据第二步,取最小的两个权值构成新树,如图:

再依次建立哈夫曼树,如下图:

其中各个权值替换对应的字符即为下图:

所以各字符对应的编码为:

A->11,B->10,C->00,D->011,E->010

霍夫曼编码是一种无前缀编码。

解码时不会混淆。

其主要应用在数据压缩,加密解密等场合。

实验代码:

#include

#include

#include

#include

#defineMAXBIT100

#defineMAXVALUE10000

#defineMAXLEAF30

#defineMAXNODEMAXLEAF*2-1

typedefstruct

{

intbit[MAXBIT];

intstart;

}HCodeType;/*编码结构体*/

typedefstruct

{

intweight;

intparent;

intlchild;

intrchild;

intvalue;

}HNodeType;/*结点结构体*/

/*构造一颗哈夫曼树*/

voidHuffmanTree(HNodeTypeHuffNode[MAXNODE],intn)

{

/*i、j:

循环变量,m1、m2:

构造哈夫曼树不同过程中两个最小权值结点的权值,

x1、x2:

构造哈夫曼树不同过程中两个最小权值结点在数组中的序号。

*/

inti,j,m1,m2,x1,x2;

/*初始化存放哈夫曼树数组HuffNode[]中的结点*/

for(i=0;i<2*n-1;i++)

{

HuffNode[i].weight=0;//权值

HuffNode[i].parent=-1;

HuffNode[i].lchild=-1;

HuffNode[i].rchild=-1;

HuffNode[i].value=i;//实际值,可根据情况替换为字母

}/*endfor*/

/*输入n个叶子结点的权值*/

for(i=0;i

{

printf("Pleaseinputweightofleafnode%d:

\n",i);

scanf("%d",&HuffNode[i].weight);

}/*endfor*/

/*循环构造Huffman树*/

for(i=0;i

{

m1=m2=MAXVALUE;/*m1、m2中存放两个无父结点且结点权值最小的两个结点*/

x1=x2=0;

/*找出所有结点中权值最小、无父结点的两个结点,并合并之为一颗二叉树*/

for(j=0;j

{

if(HuffNode[j].weight

{

m2=m1;

x2=x1;

m1=HuffNode[j].weight;

x1=j;

}

elseif(HuffNode[j].weight

{

m2=HuffNode[j].weight;

x2=j;

}

}/*endfor*/

/*设置找到的两个子结点x1、x2的父结点信息*/

HuffNode[x1].parent=n+i;

HuffNode[x2].parent=n+i;

HuffNode[n+i].weight=HuffNode[x1].weight+HuffNode[x2].weight;

HuffNode[n+i].lchild=x1;

HuffNode[n+i].rchild=x2;

printf("x1.weightandx2.weightinround%d:

%d,%d\n",i+1,HuffNode[x1].weight,HuffNode[x2].weight);/*用于测试*/

printf("\n");

}/*endfor*/

}/*endHuffmanTree*/

//解码

voiddecodeing(charstring[],HNodeTypeBuf[],intNum)

{

inti,tmp=0,code[1024];

intm=2*Num-1;

char*nump;

charnum[1024];

for(i=0;i

{

if(string[i]=='0')

num[i]=0;

else

num[i]=1;

}

i=0;

nump=&num[0];

while(nump<(&num[strlen(string)]))

{tmp=m-1;

while((Buf[tmp].lchild!

=-1)&&(Buf[tmp].rchild!

=-1))

{

if(*nump==0)

{

tmp=Buf[tmp].lchild;

}

elsetmp=Buf[tmp].rchild;

nump++;

}

printf("%d",Buf[tmp].value);

}

}

intmain(void)

{

HNodeTypeHuffNode[MAXNODE];/*定义一个结点结构体数组*/

HCodeTypeHuffCode[MAXLEAF],cd;/*定义一个编码结构体数组,同时定义一个临时变量来存放求解编码时的信息*/

inti,j,c,p,n;

charpp[100];

printf("Pleaseinputn:

\n");

scanf("%d",&n);

HuffmanTree(HuffNode,n);

for(i=0;i

{

cd.start=n-1;

c=i;

p=HuffNode[c].parent;

while(p!

=-1)/*父结点存在*/

{

if(HuffNode[p].lchild==c)

cd.bit[cd.start]=0;

else

cd.bit[cd.start]=1;

cd.start--;/*求编码的低一位*/

c=p;

p=HuffNode[c].parent;/*设置下一循环条件*/

}/*endwhile*/

/*保存求出的每个叶结点的哈夫曼编码和编码的起始位*/

for(j=cd.start+1;j

{HuffCode[i].bit[j]=cd.bit[j];}

HuffCode[i].start=cd.start;

}/*endfor*/

/*输出已保存好的所有存在编码的哈夫曼编码*/

for(i=0;i

{

printf("%d'sHuffmancodeis:

",i);

for(j=HuffCode[i].start+1;j

{

printf("%d",HuffCode[i].bit[j]);

}

printf("start:

%d",HuffCode[i].start);

printf("\n");

}

printf("Decoding?

PleaseEntercode:

\n");

scanf("%s",&pp);

decodeing(pp,HuffNode,n);

getch();

return0;

}

实验结果:

实验二

*1950年,汉明描述了构造最小距离为3的编码的一般方法,现在称为汉明码。

对于任意i值,其方法能产生(2i-1)位的编码,其中包含i个校验位和2i-1-i个信息位。

实验目的:

*理解信道编码的原理,理解汉明码的基本原理与编码过程,利用程序实现汉明码编码,理解信道编码对可靠性的追求。

实验分析:

①汉明校验的基本思想

将有效信息按某种规律分成若干组,每组安排一个校验位,做奇偶测试,就能提供多位检错信息,以指出最大可能是哪位出错,从而将其纠正。

实质上,汉明校验是一种多重校验。

②汉明校验的特点

它不仅具有检测错误的能力,同时还具有给出错误所在准确位置的能力。

一、校验位的位数校验位的位数与有效信息的长度有关

设:

N--为校验码的位数K--是有效信息位r--校验位(分成r组作奇偶校验,能产生r位检错信息)汉明码应满足N=K+r≤2r-1若r=3则N=K+r≤7所以K≤4

二.分组原则

在汉明码中,位号数(1、2、3、……、n)为2的权值的那些位,即:

1(20)、2(21)、4(22)、8(23)、…2r-1位,作为奇偶校验位

并记作:

P1、P2、P3、P4、…Pr,余下各位则为有效信息位。

例如:

N=11K=7r=4相应汉明码可示意为

位号 1 2 3 4 5 6 7 8 9 10 11

P占位P1P2×P3×××P4 × × ×

其中×均为有效信息,汉明码中的每一位分别被P1P2P3P4…Pr中的一至若干位所校验,其规律是:

第i位由校验位位号之和等于i的那些校验位所校验

如:

汉明码的位号为3,它被P1P2(位号分别为1,2)所校验

汉明码的位号为5,它被P1P3(位号分别为1,4)所校验

归并起来:

形成了4个小组,每个小组一个校验位,校验位的取值,仍采用奇偶校验方式确定。

如表2·6、表2·7所示:

 

 

三.编码、查错、纠错原理

以4位有效信息(b1、b2、b3、b4)和3位校验位(P1、P2、P3)为例:

K=4r=3

汉明序号1 2 3 4 5 6 7

汉明码  P1P2b1P3b2b3b4

根据表2-8可以看到

(1)每个小组只有一位校验位,第一组是P1、第二组是P2、第三组是P3。

(2)每个校验位校验着它本身和它后面的一些确定位。

 

1.编码原理(采用偶校验)

1)若有效信息b1b2b3b4=1011先将它们分别填入第3、5、6、7位

2)再分组进行奇偶统计,分别填入校验位P1、P2、P3的值

如:

第一组有:

P1b1b2b4因b1b2b4含偶数个1,故P1应取值为0

   第二组有:

P2b1b3b4因b1b3b4含奇数个1,故P2应取值为1

   第三组有:

P3b2b3b4因b2b3b4含偶数个1,故P3应取值为0

   汉明编码为:

P1P2b1P3b2b3b4=0110011

2.查错与纠错

因为分三组校验,每组产生一位检错信息、3组共3位检错信息,便构成一个指误字,上例指误字由G1G2G3组成。

其中:

G3=P3⊕b2⊕b3⊕b4       P3b2b3b4=0011

G2=P2⊕b1⊕b3⊕b4      P2b1b3b4=1111

G1=P1⊕b1⊕b2⊕b4      P1b1b2b4=0101

采用偶校验,在没有出错情况下G1G2G3=000。

由于在分组时,就确定了每一位参加校验的组别,所以指误字能准确地指出错误所在位。

如:

若第3位b1出错,由于b1参加了第一组和第二组的校验,必然破坏了第一组和第二组的偶性,从而使G1和G2为1。

因为b1未参加第三组校验,故G3=0,所以构成的指误字G3G2G1=011它指出第3位出错。

反之:

若G3G2G1=111则说明汉明码第7位b4出错。

因为只有第7位b4参加了3个小组的校验,破坏了三个小组的偶性。

假定:

源部件发送汉明码为:

0110011接收端接收汉明码为:

0110011

则:

三个小组都满足偶校验要求,这时G3G2G1=000,表明收到信息正确,可以从中提出有效信息1011参与运算处理。

纠错:

若接收端收到的汉明码为0110111,分组检测后指误字G3G2G1=101,它指出第5位出错,则只须将第5位变反,就可还原成正确的数码0110011。

实验代码:

//codebyzxf2010.4.10

#include

#include

#include

#include

//N代表待编码数据的上限位数

#defineN100

intHmLength(intk);//计算汉明码校验位位数

voidInCode(char*data,char*c,intk,intr);//计算汉明码每个校验位的数值

intmain()

{

intk=0,r=0,dnum=0,cnum=0;

chardata[N];

charc[N];

system("cls");

printf("NowpleaseinputthedatayouwanttoIncode:

");

for(k=0;k

{

data[k]=getche();

if(data[k]!

='0'&&data[k]!

='1')

{

break;

}

}

printf("\n__________________________________________________________\n");

r=HmLength(k);//求取校验位数

printf("k=%dr=%dThelengthofHammingcode=%d\n",k,r,r+k);//输出汉明码相关位数信息

InCode(data,c,k,r);//计算汉明码

printf("TheHammingcodeis:

");

for(intj=1;j

{

if(j==(int)pow(2,cnum))

{

printf("%c",c[cnum]);

cnum++;

}

else

{

printf("%c",data[dnum]);

dnum++;

}

}

getch();

}

/*

*@func:

计算校验码

*@param:

data待编码数据,c校验码,k数据长度,r校验码位数

*codebyzxf

*/

voidInCode(char*data,char*c,intk,intr)

{

for(inti=0;i

{

intsum=0,dnum=0,cnum=0;

for(intj=1;j

{

if(j==(int)pow(2,cnum))//去掉矩阵的全零行

{

cnum++;//记录校验码循环位数

}

else

{

intx=0,y=0;

x=pow(2,i);

y=j%(x*2);

x=y/x;//通过取余取商计算获取矩阵第r-i列第j行元素的值

sum+=data[dnum]*x;//累加乘积

dnum++;//记录数据的循环位数

}

}

c[i]=sum%2==0?

'0':

'1';//通过结果的奇偶设置校验位的值

}

}

/*

*@func:

计算校验码的位数

*@param:

k数据长度

*@return:

校验码位数

*codebyzxf

*/

intHmLength(intk)

{

intr=0,flag=1;

while(flag!

=0)//循环到2^r-1>=r+K时即得到校验码的位数

{

inttemp=0;

temp=pow(2,r);

temp=temp-1;

flag=(temp-r-k<0);

r++;

}

returnr-1;

}

实验结果:

实验三

实验分析:

卷积码的编码方法是对输入的数据流每次1比特或者K比特进行编码,输出N个编码字符。

但输出的码字的每个码元不仅与当前时刻输入的K个信息有关也和之前的M个连续输入的信息员有关。

因此卷积码是有记忆的。

输入信息序列为u=(u0,u1,…),其多项式表示为u(x)=u0+u1x+…+ulxl+…。

编码器的连接可用多项式表示为g(1,1)(x)=1+x+x2和g(1,2)(x)=1+x2,称为码的子生成多项式。

它们的系数矢量g(1,1)=(111)和g(1,2)=(101)称作码的子生成元。

以子生成多项式为阵元构成的多项式矩阵G(x)=[g(1,1)(x),g(1,2)(x)],称为码的生成多项式矩阵。

由生成元构成的半无限矩阵称为码的生成矩阵。

其中(11,10,11)是由g(1,1)和g(1,2)交叉连接构成。

编码器输出序列为c=u·G,称为码序列,其多项式表示为c(x),它可看作是两个子码序列c⑴(x)和c⑵(x)经过合路开关S合成的,其中c⑴(x)=u(x)g(1,1)(x)和c⑵(x)=u(x)g(1,2)(x),它们分别是信息序列和相应子生成元的卷积,卷积码由此得名。

在一般情况下,输入信息序列经过一个时分开关被分成k0个子序列,分别以u(x)表示,其中i=1,2,…k0,即u(x)=[u(x),…,u(x)]。

编码器的结构由k0×n0阶生成多项式矩阵给定。

输出码序列由n0个子序列组成,即c(x)=[c(x),c(x),…,c(x)],且c(x)=u(x)·G(x)。

若m是所有子生成多项式g(x)中最高次式的次数,称这种码为(n0,k0,m)卷积码。

实验代码:

#include

#include

usingnamespacestd;

inttable1[8]={1,2,4,8,16,32,64,128};

intmyn=0;//约束长度

intstalen=0;//状态个数

intstan0[256][2]={0};//输入0时个状态的输出

intstan1[256][2]={0};//输入1时各状态的输出

intstachn[256][2]={0};//状态转换表

intmyg1[10]={0};//用户输入生成序列1

intmyg2[10]={0};//用户输入生成序列2

intmyout[100];

intmyoutsym=0;

voidchartobits(charch,int*bits);

charbitstochar(int*bits);

voidconvolution(void);

//voidcreatsta(void);

voidmyoutput(int*p,intlength,intdepth);

voidmyinput(void);//用户可自行输入约束长度和编码矢量

intmain()

{

charexit_char;

myinput();

convolution();

cin>>exit_char;

}

voidmyinput(void)

{

inti,j,k,input[100]={0};

cout<<"请输入编码的约束长度M:

(3<=M<=9)";

cin>>myn;

cout<

stalen=int(pow(2.0,myn-1));

cout<<"若选择默认的编码矢量则输入1,输入2则可输入其他的编码矢量:

";

cin>>i;

cout<

cout<<"输入需要的二进制数据:

";

cin>>k;

cout<

cout<<"请输入"<

";

for(j=0;j

cin>>input[j];

cout<

if(i==1){

switch(myn){

case3:

myg1[0]=1,myg1[1]=1,myg1[2]=1;

myg2[0]=1,myg2[1]=0,myg2[2]=1;

break;

case4:

myg1[0]=1,myg1[1]=1,myg1[2]=1,myg1[3]=1;

myg2[0]=1,myg2[1]=0,myg2[2]=1,myg2[3]=1;

break;

case5:

myg1[0]=1,myg1[1]=0,myg1[2]=1,myg1[3]=1,myg1[4]=1;

myg2[0]=1,myg2[1]=1,myg2[2]=0,myg2[3]=1,myg2[4]=1;

break;

case6:

myg1[0]=1,myg1[1]=0,myg1[2]=1,myg1[3]=1,myg1[4]=1,myg1[5]=1;

myg2[0]=1,myg2[1]=1,myg2[2]=0,m

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 人文社科 > 文学研究

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

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