信息与编码理论实验报告.docx
《信息与编码理论实验报告.docx》由会员分享,可在线阅读,更多相关《信息与编码理论实验报告.docx(18页珍藏版)》请在冰豆网上搜索。
信息与编码理论实验报告
实验一:
唯一可译判决准则
1、实验目的
(1)进一步熟悉唯一可译判决准则;
(2)掌握C语言字符串处理程序的设计和调试技术。
2、实验要求
(1)已知:
信源符号个数
,码字集合
;
(2)输入:
任意一个码字集合
。
码字个数和每个具体的码字在运行时从键盘输入;
(3)输出:
判决(是唯一可译码/不是唯一可译码)。
3、算法
(1)设So为原始码字的集合,首先考察So中所有码字,如果So中有相同码字若码字,则不是唯一可译,停止;否则,若码字wj是码字wi的前缀,则将后缀列为S1中的元素;
(2)若产生的新集合为空,则为唯一可译,停止;否则转入步骤
(1)继续比较考察So和这个新的集合。
4、代码
#include
#include
#include
#include
#include
#defineTRUE1
#defineFALSE0
#defineOK1
#defineERROR0
#defineINFEASIBLE-1
#include"iostream.h"
typedefstructmazi
{
charzifu[10];
structmazi*next;
}QNode,*QueuePtr;
typedefstruct
{
QueuePtrfront;
QueuePtrrear;
}LinkQueue;
intInitQueue(LinkQueue&Q)//构造一个空的队列Q
{
Q.front=Q.rear=(QueuePtr)malloc(sizeof(QNode));
if(!
Q.front)exit(OVERFLOW);
Q.front->next=NULL;
returnOK;
}
intQueueLength(LinkQueueQ)//求队列长
{
inti=0;
QueuePtrp;
p=Q.front;
while(Q.rear!
=p)
{
i++;
p=p->next;
}
returni;
}
intEnQueue(LinkQueue&Q,chari[])//插入字符串i为Q的新队尾元素
{
QueuePtrp;
p=(QueuePtr)malloc(sizeof(QNode));
if(!
p)exit(OVERFLOW);
strcpy(p->zifu,i);
p->next=NULL;
Q.rear->next=p;
Q.rear=p;
returnOK;
}
intClearQueue(LinkQueue&Q)//清空队列
{
QueuePtrp,q;
Q.rear=Q.front;
p=Q.front->next;
Q.front->next=NULL;
while(p)
{
q=p;
p=p->next;
free(q);
}
returnOK;
}
intbijiao(LinkQueue&Q,LinkQueue&R,LinkQueue&S)//比较Q和R存入队列S中
{
QueuePtrq,r;
inti,flag=1;
q=Q.front->next;
while(q)
{
r=R.front->next;
while(r)
{
if(strcmp(q->zifu,r->zifu)==0)flag=0;//不是唯一可译码
r=r->next;
}
q=q->next;
}
if(flag)
{
q=Q.front->next;
while(q)
{
r=R.front->next;
while(r)
{
if(strlen(q->zifu)!
=strlen(r->zifu))
{
i=strlen(q->zifu)zifu)?
strlen(q->zifu):
strlen(r->zifu);
if(strncmp(q->zifu,r->zifu,i)==0)
{
chars[10],t[10];
if(strlen(q->zifu)zifu))
{
strcpy(s,r->zifu);
s[strlen(r->zifu)]='\0';
i=strlen(r->zifu)-strlen(q->zifu);
}
else
{
strcpy(s,q->zifu);
s[strlen(q->zifu)]='\0';
i=strlen(q->zifu)-strlen(r->zifu);
}
strrev(s);
strncpy(t,s,i);
t[i]='\0';
strrev(t);
EnQueue(S,t);
}
}
r=r->next;
}
q=q->next;
}
}
if(QueueLength(S))
{
ClearQueue(R);
flag=bijiao(Q,S,R);
}
returnflag;
}
intbijiao(LinkQueue&Q,LinkQueue&R)//队列Q自己比较,存入R中
{
QueuePtrq,r;
inti,flag=2;
q=Q.front->next;
while(q)
{
r=q->next;
while(r)
{
if(strcmp(q->zifu,r->zifu)==0)
{
flag=0;//不是唯一可译码
}
r=r->next;
}
q=q->next;
}
if(flag)
{
q=Q.front->next;
while(q)
{
r=q->next;
while(r)
{
if(strlen(q->zifu)!
=strlen(r->zifu))
{
i=strlen(q->zifu)zifu)?
strlen(q->zifu):
strlen(r->zifu);
if(strncmp(q->zifu,r->zifu,i)==0)
{
chars[10],t[10];
if(strlen(q->zifu)zifu))
{
strcpy(s,r->zifu);
s[strlen(r->zifu)]='\0';
i=strlen(r->zifu)-strlen(q->zifu);
}
else
{
strcpy(s,q->zifu);
s[strlen(q->zifu)]='\0';
i=strlen(q->zifu)-strlen(r->zifu);
}
strrev(s);
strncpy(t,s,i);
t[i]='\0';
strrev(t);
EnQueue(R,t);
}
}
r=r->next;
}
q=q->next;
}
}
if(flag&&!
QueueLength(R))flag=1;//唯一可译
returnflag;
}
voidmain()
{
LinkQueues0,s1,s2;
inti,N;
chars[10];
InitQueue(s0);
InitQueue(s1);
InitQueue(s2);
cout<<"请输入码字个数N:
";
cin>>N;
cout<<"请输入各码字:
";
for(i=0;i{
cin>>s;
EnQueue(s0,s);
}
if(bijiao(s0,s1)==0)cout<<"不是唯一可译码"<elseif(bijiao(s0,s1)==1)cout<<"是唯一可译码"<else
{
if(bijiao(s0,s1,s2)==0)cout<<"不是唯一可译码"<elsecout<<"是唯一可译码"<}
}
5、测试结果
实验二:
Huffman编码
1、实验目的
(1)进一步熟悉Huffman编码过程;
(2)掌握C语言递归程序的设计和调试技术。
2、实验要求
(1)输入:
信源符号个数r、信源的概率分布P;
(2)输出:
每个信源符号对应的Huffman编码的码字。
3、算法
(1)将信源U的n符号中个概率中两个概率最小的符号合并成一个新符号,新符号的概率为两个符号概率之和,得到只包含n-1个符号的缩减信源U1;
(2)依次继续,直至信源最后只剩下一个符号为止;
(3)将每次合并的两个信源符号分别用0和1码符号表示;
(4)从最后一级缩减信源开始,向前返回,就得出各信源符号所对应的码符号序列,即得各信源符号对应的码字。
4、代码
#include
#include
#include
typedefstruct{
unsignedfloatweight;
unsignedintparent,lchild,rchild;
}HTNode,*HuffmanTree;//动态分配数组存储赫夫曼树
typedefchar**HuffmanCode;//动态分配数组存储赫夫曼编码表
voidHuffmanCoding(HuffmanTree&HT,HuffmanCode&HC,float*w,intn)
{//w存放n个字符的权值(均>0),构造赫夫曼树HT,并求出n个字符的赫夫曼编码HC。
if(n<1)return;
voidSelect(HuffmanTreeHT,inta,int&a1,int&a2);
HuffmanTreep;
inti,s1,s2,f,c,m,start;
char*cd;
m=2*n-1;
HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode));//0号单元为空
for(p=HT+1,i=1;i<=n;i++,p++,w++)
{
p->weight=*w;p->parent=0;
p->lchild=0;p->rchild=0;
}
for(i=n+1;i<=m;i++,p++)
{
p->weight=0;p->parent=0;
p->lchild=0;p->rchild=0;
}
for(i=n+1;i<=m;i++){//建赫夫曼树
//在HT[1..i-1]选择parent为0且weight最小的两个结点,其序号分别为s1和s2.
Select(HT,i-1,s1,s2);
HT[s1].parent=i;HT[s2].parent=i;
HT[i].lchild=s1;HT[i].rchild=s2;
HT[i].weight=HT[s1].weight+HT[s2].weight;
}
//从叶子到根逆向求每个字符的赫夫曼编码
HC=(HuffmanCode)malloc((n+1)*sizeof(char*));//分配n个字符编码的头指针向量
cd=(char*)malloc(n*sizeof(char));//分配求编码的工作空间
cd[n-1]='\0';//编码结束符
for(i=1;i<=n;i++){//逐个字符求赫夫曼编码
start=n-1;//编码结束符位置
for(c=i,f=HT[i].parent;f!
=0;c=f,f=HT[f].parent)//从叶子到根逆向求编码
{
if(HT[f].lchild==c)cd[--start]='0';
elsecd[--start]='1';
}
HC[i]=(char*)malloc((n-start)*sizeof(char));//为第i个字符编码分配空间
strcpy(HC[i],&cd[start]);//从cd复制编码(串)到HC
}
free(cd);//释放工作空间
}
voidSelect(HuffmanTreeHT,inta,int&a1,int&a2)
{
intj;
intmin1;
intmin2;
for(j=1;j<=a;j++)
if(HT[j].parent==0)
{
min1=HT[j].weight;
a1=j;
break;
}
for(j=1;j<=a;j++)
{
if(HT[j].parent==0&&HT[j].weight{
min1=HT[j].weight;
a1=j;
}
}
for(j=1;j<=a;j++)
if(HT[j].parent==0&&j!
=a1)
{
min2=HT[j].weight;
a2=j;
break;
}
for(j=1;j<=a;j++)
{
if(HT[j].parent==0&&HT[j].weight=a1)
{
min2=HT[j].weight;
a2=j;
}
}
}
voidmain()
{
float*w;
intn,i;
HuffmanTreeHT;
HuffmanCodeHC;
HT=NULL;
HC=NULL;
printf("请输入信源符号个数n:
");
scanf("%d",&n);
w=(float*)malloc(n*sizeof(float));
printf("请依次输入各信源符号的概率:
");
for(i=0;iHuffmanCoding(HT,HC,w,n);
for(i=0;iprintf("第%d个信源符号的概率为%f,赫夫曼编码为:
%s\n",i+1,w[i],HC[i+1]);
}
5、测试结果
实验三:
LZW编码
1、实验目的:
(1)进一步熟悉通用编码算法;
(2)掌握C语言程序设计和调试过程中数值的进制转换、数值与字符串之间的转换等技术。
2、实验要求:
(1)输入:
本程序将从标准输入中读入待压缩的数据流;
(2)输出:
将压缩结果输出到标准输出上去。
3、算法:
(1)将待编码信源序列中的所有单个字符存入串表中,并给每个符号赋一个码字值;
(2)读入第一个输入字符,赋给前缀变量P;
(3)读入下一个输入字符,赋给前缀变量S;
(4)如果S为空,输出P,停止;否则执行步骤5;
(5)如果PS不在串表中,则将P对应的码字值输出,将PS存入串表,并分配一个码字值,同是将扩展字符S赋给P;否则将PS赋给P;
4、代码:
#include"stdio.h"
#include"stdlib.h"
#include"string.h"
#include"iostream.h"
typedefstructzifu
{
chara[30];
};
voidmain()
{
structzifu*x,*y;
inti,j,k,N,flag;
chars[30],p[30],q[30],z[30];
cout<<"请输入信源个数:
";
cin>>N;
x=y=(zifu*)malloc(N*sizeof(zifu));
cout<<"请输入信源序列:
";
for(i=0;i>x[i].a;
for(i=0;ik=0;
strcpy(y[0].a,x[0].a);
for(i=1;i{
flag=1;
for(j=0;j<=k;j++)if(strcmp(y[j].a,x[i].a)==0)flag=0;
if(flag)
{
k++;
strcpy(y[k].a,x[i].a);
}
}
cout<<"可将信源编码为:
"<strcpy(p,&z[0]);
p[1]='\0';
for(i=1;i{
strcpy(s,&z[i]);
s[1]='\0';
flag=1;
strcpy(q,p);
strcat(q,s);
for(j=0;j<=k;j++)if(strcmp(q,y[j].a)==0)flag=0;
if(flag)
{
k++;
strcpy(y[k].a,q);
for(j=0;jstrcpy(p,s);
}
else
{
strcpy(p,q);
}
}
for(j=0;j<=k;j++)if(strcmp(p,y[j].a)==0)cout<cout<<"输出字符串序列:
"<for(j=0;j<=k;j++)cout<}
5、测试结果