信息论课程设计.docx
《信息论课程设计.docx》由会员分享,可在线阅读,更多相关《信息论课程设计.docx(25页珍藏版)》请在冰豆网上搜索。
信息论课程设计
电子科技大学电子工程学院
信息论课程设计报告
课程名称:
信息编码与加密
课程设计报告
学生姓名:
农瀚学号:
2014020908021指导教师:
李万春
一、课程设计名称:
编程实现霍夫曼、费诺、香农编码
二、课设原理:
1)霍夫曼编码:
霍夫曼编码的平均码长最短,是最佳编码。
编码步骤如下:
(1)将信源符号按概率大小排序;
(2)对概率最小的两个符号求其概率之和,同时给两幅号分别赋予码元0和1;
(3)将概率之和当做一个新符号的概率。
与剩下的概率一起,形成一个缩减信源,再重复上述步骤,直到概率和为1为止;
(4)按上述步骤实际上构成了一个码树,从根到端点经过的树枝即为码字。
2)费诺编码:
编码步骤如下:
(1)将信源概率从大到小排序;
(2)将信源符号分成两组,使两组信源符号的概率之和近似相等,并给两组信源符号分别赋0和1;
(3)再把各个小组的信源符号细分为两组并赋码元,方法与第一次分组相同;
(4)如此一直下去,直到每一个小组只含一个信源符号为止;
(5)由此可构造成一个码树,所有终端节点上的码字组成费诺码。
3)香农编码:
编码方法如下:
⑴ 将信源消息符号按其出现的概率大小依次排列
p(u1)≥p(u2)≥…≥ p(un)
⑵ 确定码长Ki (整数) :
Ki=[
]——取整
⑶ 为了编成唯一可译码,计算第i个消息的累加概率
⑷ 将累加概率Pi变换成二进制数。
⑸ 取pi二进制数的小数点后Ki位即为该消息符号的二进制数。
三、课设目的:
通过编程实现三种方式的编码,掌握三种编码方式的步骤。
四、课设内容:
三种编码方式的编程思路:
1、霍夫曼编码:
(1)对给定的n个权值{W1,W2,W3,...,Wi,...,Wn}构成n棵二叉树的初始集合F={T1,T2,T3,...,Ti,...,Tn},其中每棵二叉树Ti中只有一个权值为Wi的根结点,它的左右子树均为空。
(为方便在计算机上实现算法,一般还要求以Ti的权值Wi的升序排列。
)
(2)在F中选取两棵根结点权值最小的树作为新构造的二叉树的左右子树,新二叉树的根结点的权值为其左右子树的根结点的权值之和。
(3)从F中删除这两棵树,并把这棵新的二叉树同样以升序排列加入到集合F中。
(4)重复二和三两步,直到集合F中只有一棵二叉树为止。
2、费诺编码的编程思路:
(1)先使用冒泡法对信源概率概率排序;
(2)依次将按排好序的符号概率进行近似1:
1分成两大组;
(3)对各组赋予一个二进制码元“0”和“1”;
(4)输出符号,符号概率及编码。
3、香农编码:
(1)对于一个给定的符号列表,制定了概率相应的列表或频率计数,使每个符号的相对发生频率是已知。
(2)排序根据频率的符号列表,最常出现的符号在左边,最少出现的符号在右边。
(3)清单分为两部分,使左边部分的总频率和尽可能接近右边部分的总频率和。
(4)该列表的左半边分配二进制数字0,右半边是分配的数字1。
这意味着,在第一半符号代都是将所有从0开始,第二半的代码都从1开始。
(5)对左、右半部分递归应用步骤3和4,细分群体,并添加位的代码,直到每个符号已成为一个相应的代码树的叶。
五、器材(设备、元器件):
计算机、visualstudio2017社区版
六、设计代码:
见附录
九、实验数据及结果
根据上述实验程序得到的实验数据及结果如下:
霍夫曼编码:
费诺编码:
香农编码:
十、结论
完成了20个非等概随机信源的霍夫曼、费诺和香农编码,并给出了编码效率和码字。
十一、总结及心得体会
通过这次课程设计,我掌握了三种编码方式的步骤,并能够利用编程实现编码,提高了自己的编程水平和对该知识点的掌握程度。
附录代码:
//ConsoleApplication1.cpp:
定义控制台应用程序的入口点。
//
/*******霍夫曼编码*************/
#include"stdafx.h"
#include
#include
#include
#include
#include
#include
usingnamespacestd;
#defineSourNum20
#defineMAXBIT100
#defineMaxValue10000
#defineMAXLEAF30
#defineMAXNODEMAXLEAF*2-1
doubleSp[SourNum];
charcoder[100][100];
intbitlong[100];
voidProSource()//产生非等概信源的函数
{
intn=0;
srand((unsigned)time(0));
doublesum=0;
while
(1)
{
Sp[n]=(double)rand()/(RAND_MAX);//产生随机浮点数
sum=sum+Sp[n];
if(sum<1&&Sp[n]<0.086)
{
n++;
if(n>19)
break;
elsecontinue;
}
else
{
sum=sum-Sp[n];
Sp[n]=0;
continue;
}
}
Sp[SourNum]=1-sum;
}
/*******霍夫曼编码*************/
typedefstruct
{
intbit[MAXBIT];
intstart;
}HCode;
typedefstruct
{
doubleweight;
doubleparent;
doublelchild;
doublerchild;
intlast;
}HNodeType;
voidHuffmanTree(HNodeTypeHuffNode[MAXNODE],intn)
{
inti,j,x1,x2;;
doublem1,m2;
for(i=0;i<2*n-1;i++)
{
HuffNode[i].weight=0;
HuffNode[i].parent=-1;
HuffNode[i].lchild=-1;
HuffNode[i].rchild=-1;
}
for(i=0;i{
HuffNode[i].weight=Sp[i];
}
for(i=0;i{
m1=m2=MaxValue;
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;
}
}
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;
}
}
doubleCodEffi()//求编码效率
{
intAveraLong=0,SumLong=0;
doubleH=0,CE=0;
for(inti=0;i{
SumLong=SumLong+bitlong[i];
}
AveraLong=SumLong/SourNum;
for(intj=0;j{
H=(-Sp[j])*(log(Sp[j])/log
(2))+H;
}
CE=H/AveraLong;
returnCE;
}
intmain()
{
ProSource();
sort(Sp,Sp+SourNum);
HNodeTypeHuffNode[MAXNODE];
HCodeHuffCode[MAXLEAF],cd;
inti,j,c,p,n;
n=SourNum;
HuffmanTree(HuffNode,SourNum+1);
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;
}
for(j=cd.start+1;j{
HuffCode[i].bit[j]=cd.bit[j];
}
HuffCode[i].start=cd.start;
}
memset(coder,'\0',sizeof(coder));
inttemp=0;
for(i=0;i{
cout<<"信源"<
";
for(j=HuffCode[i].start+1;j{
cout<coder[i][temp]=char(HuffCode[i].bit[j]+48);
temp++;
}
temp=0;
cout<<"信源概率:
"<cout<<"字长:
"<printf("\n");
bitlong[i]=strlen(coder[i]);
}
CodEffi();
cout<<"\n编码效率:
"<return0;
}
//费诺编码.cpp:
定义控制台应用程序的入口点。
//
#include"stdafx.h"
#include
#include
#include
#include
#include
#include
#include
#defineBmax10
#defineSmax20
usingnamespacestd;
#defineSourNum20
doubleSp[SourNum];
intbitlong[100];
voidgroup1(intlow,intmid,inthigh);
voidcode(intlow,intmid,inthigh);
voidProSource()//产生非等概信源的函数
{
intn=0;
srand((unsigned)time(0));
doublesum=0;
while
(1)
{
Sp[n]=(double)rand()/(RAND_MAX);//产生随机浮点数
sum=sum+Sp[n];
if(sum<1&&Sp[n]<0.086)//
{
n++;
if(n>19)
break;
elsecontinue;
}
else
{
sum=sum-Sp[n];
Sp[n]=0;
continue;
}
}
Sp[SourNum]=1-sum;
}
structBit
{
charb[Bmax];//定义码长度数组的数据类型字符型组成成员
intlast;
};
typedefstructsymbol
{
intc;
doubleprobability;
structBitbit;
}sbl;
sbls[Smax];
/********输入符号的符号概率********/
voidinput(intn)
{
inti;
intc;
for(i=0;i{
s[i].c=i;
s[i].probability=Sp[i];
}
}
/***********用冒泡法排序**********/
voidcode(intlow,intmid,inthigh)
{
inti;
for(i=low;i{
if(i{
s[i].bit.b[s[i].bit.last]='0';
s[i].bit.last++;
}
else
{
s[i].bit.b[s[i].bit.last]='1';
s[i].bit.last++;
}
}
}
voidsort(intn)
{
doublet;
chara;
inti,j;
for(i=1;ifor(j=0;jif(s[j].probability
{
t=s[j].probability;
a=s[j].c;
s[j].probability=s[j+1].probability;
s[j].c=s[j+1].c;
s[j+1].probability=t;
s[j+1].c=a;
}
}
/************分组函数************/
voidgroup(intn)
{
inti,pmid,plow,phigh;
pmid=phigh=n;
plow=0;
for(i=0;is[i].bit.last=0;
group1(plow,pmid,phigh);
}
voidgroup1(intlow,intmid,inthigh)
{
doubled,dmin;
d=0;
inti;
if(high==low+1)
return;
for(i=low;id+=s[i].probability;
dmin=d-2*s[low].probability;
for(i=low+1;i{
d=fabs(dmin-2*s[i].probability);
if(ddmin=d;
else
break;
}
mid=i;
code(low,mid,high);
group1(low,mid,mid);
group1(mid,high,high);
}
voidoutput(intn)
{
inti,j;
printf("费诺编码输出信源,概率及编码:
\n\n");
for(i=0;i{
cout<<"信源:
"<
"<
";
for(j=0;j
cout<
bitlong[i]=s[i].bit.last;
cout<<""<<"字长"<printf("\n");
}
}
doubleCodEffi()
{
intAveraLong=0,SumLong=0;
doubleH=0,CE=0;
for(inti=0;i{
SumLong=SumLong+bitlong[i];
}
AveraLong=SumLong/SourNum;
for(intj=0;j{
H=(-Sp[j])*(log(Sp[j])/log
(2))+H;
}
CE=H/AveraLong;
returnCE;
}
voidmain()//主函数
{
intn=SourNum;//定义变量
ProSource();
input(n);//分别调用输入、排序、分组、输出函数,并执行
sort(n);
group(n);
output(n);
cout<<"\n编码效率:
"<}
//香农编码.cpp:
定义控制台应用程序的入口点。
//
#include"stdafx.h"
#include
#include
#include
#include
#include
#include
#include
#include
#defineBmax10//最长码长度
#defineSmax20
usingnamespacestd;
#defineSourNum20
doubleSp[SourNum];
intbitlong[100];
structshan
{
ints;
doublep;
doublepadd;
doublel_f;
intl;
charw[20];
};
shanSourData[SourNum];
voidgroup1(intlow,intmid,inthigh);
voidcode(intlow,intmid,inthigh);
voidProSource()//产生非等概信源的函数
{
intn=0;
srand((unsigned)time(0));
doublesum=0;
while
(1)
{
Sp[n]=(double)rand()/(RAND_MAX);//产生随机浮点数
sum=sum+Sp[n];
if(sum<1&&Sp[n]<0.086)//
{
n++;
if(n>19)
break;
elsecontinue;
}
else
{
sum=sum-Sp[n];
Sp[n]=0;
continue;
}
}
Sp[SourNum]=1-sum;
}
inti,j,n,k,b;
doubleaddp;
charbitw[20];
voidsequ(structshanx[],intn)
{
structshantemp;
for(i=0;ifor(j=i;j{
if(x[i].p{
temp=x[j];
x[j]=x[i];
x[i]=temp;
}
}
}
voidcountpadd(structshanx[],intn)
{
addp=0;
x[0].padd=0;
for(i=0;i{
addp+=x[i].p;
x[i+1].padd=addp;
}
}
voidcount_l(structshanx[],intn)
{
for(i=0;i{
x[i].l_f=-log(x[i].p)/log
(2);
if((x[i].l_f-(int)x[i].l_f)>0)
x[i].l=(int)x[i].l_f+1;
elsex[i].l=(int)x[i].l_f;
}
}
voidcovbit(doublea,intlc)
{
for(j=0;j{
b=(int)(a*2);
bitw[j]=b+48;
a=2*a-int(a*2);
}
}
doubleCodEffi()
{
intAveraLong=0,SumLong=0;
doubleH=0,CE=0;
for(inti=0;i