信息理论与编码实验指导书.docx
《信息理论与编码实验指导书.docx》由会员分享,可在线阅读,更多相关《信息理论与编码实验指导书.docx(45页珍藏版)》请在冰豆网上搜索。
信息理论与编码实验指导书
信息理论与编码实验指导书
解振东编写
信息科学与技术学院
实验一:
香农(Shannon)编码
一、实验目的
掌握通过计算机实现香农编码的方法。
二、实验要求
对于给定的信源的概率分布,按照香农编码的方法进行计算机实现。
三、实验基本原理
给定某个信源符号的概率分布,通过以下的步骤进行香农编码
1.将信源消息符号按其出现的概率大小排列
2.确定满足下列不等式的整数码长Ki;
3.为了编成唯一可译码,计算第i个消息的累加概率
4.将累加概率Pi变换成二进制数。
5.取Pi二进制数的小数点后Ki位即为该消息符号的二进制码。
四实验内容
1.对给定信源
进行二进制香农编码。
2.对给定信源
进行二进制香农编码。
3.自已选择一个例子进行香农编码。
五、实验设备
PC计算机,C++
六、实验报告要求
1、画出程序设计的流程图,
2、写出程序代码,
3、写出在调试过程中出现的问题,
4、对实验的结果进行分析。
七、参考程序(仅供参考)
//香农(Shannon)编码参考程序
intmain()
{
intN;
cout<<”请输入信源符号个数:
”;cin>>N;
cout<<”请输入各符号的概率:
”<double*X=newdouble[N];//离散无记忆信源
inti,j;
for(i=0;i{
cout<<”X[”<>X[i];
}
//由小到大排序
for(i=0;ifor(j=i+1;jif(X[i]{doubletemp=X[i];X[i]=X[j];X[j]=temp;}
int*K=newint[N];//确定码长
for(i=0;i{
K[i]=int(-(log(X[i])/log
(2)))+1;//确认码长为1-log2(p(xi))
if(K[i]==(-(log(X[i])/log
(2)))+1)//当K[i]=-log2(p(xi))时,K[i]--
K[i]--;
}
//累加概率
double*Pa=newdouble[N];pa[0]=0.0;
for(i=1;ipa[i]=pa[i-1]+X[i-1];
//将累加概率转换为二进制
string*code=newstring[N];
for(i=0;ifor(j=0;j{
doubletemp=Pa[i]*2;
if(temp>=1)//累加概率乘2大于1,对应码字加1,累加概率自身取余
{
code[i]+=”1”;
Pa[i]=Pa[i]*2-1;
}
else//累加概率乘2小于1时,对应码字加0,累加概率自身取余
{
code[i]+=”0”;
Pa[i]*=2;
}
}
for(i=0;icode[i]=code[i].substr(0,K[i]);//求码字
//输出码字
cout<for(i=0;icout<delete[]X;
delete[]Pa;
delete[]K;
delete[]code;
getch();
retuen0;
}
实验二费诺编码
一、实验目的
掌握通过计算机实现费诺编码。
二、实验要求
对于给定的信源的概率分布,按照费诺编码的方法进行计算机实现。
三、实验基本原理
费诺编码的步骤:
1.将概率按从大到小的顺序排列;
2.按编码进制数将概率分组,使每组概率和尽可能接近或相等;
3.给每组分配一位码元;
4.将每一分组再按同样原则划分,重复2和3,直到概率不再可分为止。
四实验内容
1.对给定信源
进行二进制费诺编码。
2.对给定信源
进行二进制费诺编码。
3.自已选择一个例子进行费诺编码。
五、实验设备
PC计算机,C++
六、实验报告要求
1、画出程序设计的流程图,
2、写出程序代码,
3、写出在调试过程中出现的问题,
4、对实验的结果进行分析。
七、参考程序(仅供参考)
//********费诺编码参考程序1****
//全局变量定义
intn;
string*sign;
double*p;
string*code;
voidfano(inta,intb)//费诺编码函数
{
if((b-a)>=1)//判断该组中符号个数是否大于2
{
doublesum=0;
for(inti=a;i<=b;i++)
sum+=p[i];//计算该组概率累加和
doubles1=0,*s=newdouble[10];
for(inti=a;i<=b;i++)
{
s1+=p[i];s[i]=fabs(2*s1-sum)/sum;
}
doublemin=s[a];intc;
for(inti=a;i<=b;i++)
if(s[i]<=min)
{
min=s[i];c=i;//定位使两组概率和尽可能相近或相等的位置c
}
for(inti=a;i<=b;i++)
{
if(i<=c)code[i]+=”0”;//码字加“0”
elsecode[i]+=”1”;//码字加“1”
}
//判断分组点位置,进而分情况自身调用
if(c==a)
fano(c+1,b);
elseif(c==b-1)
fano(a,c);
else
{fano(a,c);fano(c+1,b);}
}
}
voidmain()
{
cout<<””请输入信源符号个数n:
”;
cin>>n;
p=newdouble[n];
sign=newstring[n];
code=newstring[n];
cout<<”请输入信源符号:
”;
for(inti=0;i>sign[i];
cout<<”请输入信源符号的概率:
”;
for(inti=0;i>p[i];
for(inti=0;ifor(intj=i+1;jif(p[i]
{
doubletemp=p[i];p[i]=p[j];p[j]=temp;
stringm=sign[i];sign[i]=sign[j];sign[j]=m;
}
fano(0,n-1);//费诺编码
cout<for(inti=0;icout<delete[]p;delete[]sign;delete[]code;
}
//***********费诺编码参考程序2*************
#include
#include
usingnamespacestd;
classDATA//数据类,采用双向表
{
public:
//初始化PXi=1是为了在排序迭代时方便
DATA(){next=NULL;pre=NULL;r=NULL;PXi=1;key[0]='\0';key[1]='\0';key[2]='\0';key[3]='\0';key[4]='\0';key[5]='\0';
key[6]='\0';key[7]='\0';key[8]='\0';key[9]='\0';key[10]='\0';}
charXi;//信源符号
doublePXi;//信源概率
charkey[11];//码字
DATA*next,*pre,*r;//地址
};
DATA*head=newDATA,*p=head;
intk=(-1);//编码函数用
voidencoding(DATA*pp);//编码函数声明
DATA*sort(DATA*pp);//排序函数声明
DATA*HEAD=newDATA,*tt=HEAD,*T;//排序函数用
voidinput()//输入数据
{
doublel,sum=0;
intn,i;
charL;
cout<<"请输入信源个数:
";
cin>>n;
for(i=0;i{
cout<<"请输入一个字符的信源符号:
"<>L;
cout<<"请输入概率:
"<>l;
p->Xi=L;
p->PXi=l;
sum=sum+p->PXi;
p->next=newDATA;
p->next->pre=p;//对新创建结点赋值
p->r=p->next;
p=p->next;
}
if(sum!
=1)
{
cout<<"所输入的概率之和是"<input();
}
T=sort(head);//因为sort要改变tt,故需要一个中间变量
tt->next=T;//由于迭代产生的链表格式不规范,以下句用来整理sort函数的返回结果
tt->next->pre=tt;
tt=tt->next;
tt->next=newDATA;
tt->next->pre=tt;//对新创建结点赋值
tt=tt->next;
HEAD->next->next->pre=NULL;
HEAD=HEAD->next->next;
cout<<"对输入信源排序结果如下:
"<for(p=HEAD;p->next!
=NULL;p=p->next)//排序输出
cout<Xi<<":
"<PXi<cout<<"对输入信源编码结果如下:
"<encoding(HEAD);
}
/***********************编码************************/
voidencoding(DATA*pp)//定义递归函数
{
doubley=1;//y定义为1是因为概率最多为1
k++;//递归自增值,用于字符数组定位
DATA*head1=pp,*head2;
into=1;
while
(1)//分01组
{
doublel=0,z=0;
for(inti=1;i<=o;i++)
{
if(pp->next==NULL)break;
l=l+pp->PXi;
pp=pp->next;
}
head2=pp->pre;//从这里分01段
for(;pp->next!
=NULL;pp=pp->next)
z=z+pp->PXi;
if(y>fabs(l-z))//判断两组值之差是否最小
{
y=fabs(l-z);
pp=head1;
o++;
continue;
}
elseif(z==0&&i<=2)//z=0,i<1表示只有一个概率了
{
cout<Xi<<":
"<key<break;
}
for(DATA*u=head1;u->next!
=head2->next;u=u->next)
u->key[k]='0';//为字符串赋值
for(DATA*h=head2;h->next!
=NULL;h=h->next)
h->key[k]='1';
head2->pre->next=newDATA;//分段:
标记head2为上一段结束位置
head2->pre->next->pre=head2->pre;
encoding(head1);//递归
encoding(head2);
break;
}
k--;//迭代还原到上一个数组位置
}
DATA*sort(DATA*pp)
{//函数递归后头变到HEAD->next->next.返回值得到最后个head2没有与tt相连,需另设.得不到结尾为空的(next=MULL)地址
DATA*head1=pp,*head2=pp;
if(pp->next==NULL)returnpp;//当pp是最后一个值时
for(;pp->next!
=NULL;pp=pp->next)
{
if(1-pp->PXi>=1-head2->PXi)//两个以上的值时,由于最后一个pxi为1,所以每次都会有个最小值
head2=pp;
}
if(head2->pre==NULL)//当pp是第一个值时
{
head2->next->pre=NULL;
head1=head1->next;
}
else//当pp是最后一个值及中间的值时
{
head2->pre->next=head2->next;
head2->next->pre=head2->pre;
}
tt->next=sort(head1);//递归,先得第一个,再得下一个
tt->next->pre=tt;
tt=tt->next;
returnhead2;
}
voidmain()
{
cout<<"************费诺编码************"<input();
cout<}
实验三霍夫曼编码
一、实验目的
掌握通过计算机实现霍夫曼编码
二、实验要求
对于给定的信源的概率分布,按照霍夫曼编码的方法进行计算机实现。
三、实验基本原理
霍夫曼编码的步骤:
(1).把信源符号按概率大小顺序排列,并设法按逆次序分配码字的长度。
(2).在分配码字长度时,首先将出现概率最小的两个符号的概率相加合成一个概率
(3).把这个合成概率看成是一个新组合符号地概率,重复上述做法直到最后只剩下两个符号概率为止。
(4).完成以上概率顺序排列后,再反过来逐步向前进行编码,每一次有二个分支各赋予一个二进制码,可以对概率大的赋为0,概率小的赋为1。
四实验内容
1.对给定信源
进行二进制霍夫曼编码。
2.对给定信源
进行二进制霍夫曼编码。
3.自已选择一个例子进行霍夫曼编码。
五、实验设备
PC计算机,C++
六、实验报告要求
1、画出程序设计的流程图,
2、写出程序代码,
3、写出在调试过程中出现的问题,
4、对实验的结果进行分析。
七、参考程序(仅供参考)
//第一段参考代码
#include
#include
#include//forsetw
usingnamespacestd;
//====================
typedefstruct
{
intweight;
intparent;
intlchild;
intrchild;
}hnodetype;//霍夫曼树节点
typedefstruct
{
intbit[10];
intposition;
charsign;
}hcodetype;//霍夫曼编码表
//=======================
voidHuffman(intm[],intn);//函数声明
intmain()
{
inti=0,n=8;
intm[10]={40,18,10,10,7,6,5,4};
charsign[10]="hufmcode";
cout<";
for(i=0;icout<cout<";
for(i=0;i{
floatf=(float)m[i]/100;
cout<}
cout<"<Huffman(m,n);
getch();
return0;
}
//====================================
voidHuffman(intm[],intn)
{
inti,j,m1,m2,x1,x2,c,p;
hnodetype*huffnode=newhnodetype[2*n-1];//一共2n-1个节点
hcodetype*huffcode=newhcodetype[n],temp;
for(i=0;i<2*n-1;i++)
{//初始化霍夫曼树
huffnode[i].weight=0;
huffnode[i].parent=0;
huffnode[i].lchild=1;
huffnode[i].rchild=1;
}
for(i=0;i{//节点赋初值
huffnode[i].weight=m[i];
huffcode[i].sign=sign[i];
}
//对n到2n-1节点编码
for(i=0;i{
m1=m2=100;
x1=x2=0;
for(j=0;j{
if(huffnode[j].weight<=m1&&huffnode[j].parent==0)
{
m2=m1;x2=x1;
m1=huffnode[j].weight;
x1=j;
}
elseif(huffnode[j].weight<=m2&&huffnode[j].parent==0)
{
m2=huffnode[j].weight;
x2=j;
}
}
huffnode[x1].parent=n+i;//定义x1和x2的父节点为n+i
huffnode[x2].parent=n+i;
huffnode[n+i].weight=huffnode[x1].weight+huffnode[x2].weight;
huffnode[n+i].lchild=x1;//新节点的左、右孩子分别为x1、x2
huffnode[n+i].rchild=x2;
}
//从叶子到根逆向求每个字符的霍夫曼编码
for(i=0;i{
temp.position=n-1;
c=i;
p=huffnode[c].parent;
while(p!
=0)//如果p节点不是根节点则一直向上编码
{
if(huffnode[p].lchild==c)//如果p节点的左孩子是c,则码字加1
temp.bit[temp.position]=1;
else//否则则码字加0
temp.bit[temp.position]=0;
temp.position--;//记录当前码字存储位置
c=p;p=huffnode[c].parent;//从新定义c和p的指向
}
cout<";
for(j=temp.position+1;j{//输出码字
huffcode[i].bit[j]=temp.bit[j];
cout<}
cout<}
delete[]huffcode;
delete[]huffnode;
}
//第二段参考代码
#include
#include
#include
#include
#include
//------
typedefstruct{
unsignedintweight;
unsignedintparent,lchild,rchild;
}HTNode,*HuffmanTree;
typedefchar**HuffmanCode;
typedefstruct{
unsignedints1;
unsignedints2;
}MinCode;
voidError(char*message);
HuffmanCodeHuffmanCoding(HuffmanTreeHT,HuffmanCodeHC,unsignedint*w,unsignedintn);
MinCodeSelect(HuffmanTreeHT,unsignedintn);
voidError(char*message)
{
clrscr();
fprintf(stderr,"Error:
%s",message);
exit
(1);
}
HuffmanCodeHuffmanCoding(HuffmanTreeHT,HuffmanCodeHC,unsignedint*w,unsignedintn)
{
unsignedinti,s1=0,s2=0;
HuffmanTreep;
char*cd;
unsignedintf,c,start,m;
MinCodemin;
if(n<=1)Error("Codetoosmall!
");
m=2*n-1;
HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode));
for(p=HT,i=0;i<=n;i++,p++,w++)
{
p->weight=*w;
p->parent=0;
p->lchild=0;
p->r