信息论与编码课程设计报1.docx

上传人:b****2 文档编号:23483863 上传时间:2023-05-17 格式:DOCX 页数:23 大小:320.40KB
下载 相关 举报
信息论与编码课程设计报1.docx_第1页
第1页 / 共23页
信息论与编码课程设计报1.docx_第2页
第2页 / 共23页
信息论与编码课程设计报1.docx_第3页
第3页 / 共23页
信息论与编码课程设计报1.docx_第4页
第4页 / 共23页
信息论与编码课程设计报1.docx_第5页
第5页 / 共23页
点击查看更多>>
下载资源
资源描述

信息论与编码课程设计报1.docx

《信息论与编码课程设计报1.docx》由会员分享,可在线阅读,更多相关《信息论与编码课程设计报1.docx(23页珍藏版)》请在冰豆网上搜索。

信息论与编码课程设计报1.docx

信息论与编码课程设计报1

 

信息论与编码课程设计报告

 

姓名:

时旭东

专业:

电科10-01

学号:

311008002320

指导老师:

成凌飞

完成日期:

2013.03.20

 

目录

一.课程描术。

1

二.设计原理。

2

三.设计内容。

3

四.总结。

22

五.参考文献。

23

一.课程设计教学目的

通过本次课程设计的练习,使学生进一步巩固信源熵、信源编码的基本原理,掌握具体的编码方法,熟悉编程软件的使用,培养学生自主设计、编程调试的开发能力,同时提高学生的实践创新能力。

二.题目一:

判断唯一可译码

一.设计要求:

利用尾随后缀法判断任意输入的码是否为唯一可译码。

二.题目分析:

设计一个程序实现判断输入码组是否为唯一可译码这一功能。

在我们学习使用了克劳夫特不等式之后,知道唯一可译码必须满足克劳夫特不等式。

但是克劳夫特不等式仅仅是存在性的判定定理,即该定理不能作为判断一种码是否为唯一可译码的依据。

也就是说当码字长度和码符号数满足克劳夫特不等式时,则必可以构造出唯一可译码,否则不能构造出唯一可译码。

因此我们必须找到一种能够判断一种码是否为唯一可译码的方法—尾随后缀法。

三.算法分析:

尾随后缀法算法描述:

设C为码字集合,按以下步骤构造此码的尾随后缀集合F:

(1)考查C中所有的码字,若Wi是Wj的前缀,则将相应的后缀作为一个尾随后缀放入集合F0中;

(2)考查C和Fi两个集合,若Wj∈C是Wi∈Fi的前缀或Wi∈Fi是Wj∈C的前缀,则将相应的后缀作为尾随后缀码放入集合Fi+1中;

(3)F=∪Fi即为码C的尾随后缀集合;

(4)若F中出现了C中的元素,则算法终止,返回假(C不是唯一可译码);否则若F中没有出现新的元素,则返回真。

在我们设计的算法中,需要注意的是我们需要的是先输出所有尾随后缀的集合,然后再判断该码是否是唯一可译码,即如F中出现了C中的元素,则C不是唯一可译码,否则若F中没有出现新的元素,则C为唯一可译码。

而不是F中出现C中的元素就终止,这也是在本题的要求中需要注意的问题。

简明流程图

开始

输入码字个数和码字

 

进行尾随后缀编码

 

判断是否为唯一码

 

调用main()函数

 

结束

 

四.概要设计:

由于需要判断尾随后缀,所以我们需要反复的比较C和F中的码字。

1)首先我们用一个b[40][40]的数组来存放所有的尾随后缀的集合;用Q记录所有尾随后缀的个数;

2)用数组a[40][40]来存放输入的码字,L[50]来存放码字的长度;

通过一个双重循环并调用Hz(a[i],a[j],L[i],L[j])函数来找到a[40][40]中的为随后缀,即:

for(i=0;i

{

for(j=0;j

{

if(i!

=j&&L[i]

Hz(a[i],a[j],L[i],L[j]);

}

}

3)通过判断Q是否大于0,如果不大于0,即b[40][40]中没有码字,也就是不存在尾随后缀,那么可判断a[40][40]是唯一可译码,否则进行如下操作;

4)计算b[40][40]中尾随后缀的长度,用k1表示;并调用Hz(b[i],a[j],k1,L[j])其中k1

for(i=0;i

{

k1=strlen(b[i]);

for(j=0;j

{

if(k1

Hz(b[i],a[j],k1,L[j]);

}

}

5)寻找b[40][40]中的尾随后缀;用k2表示b[40][40]中码字的长度,并调用Hz(a[i],b[j],L[i],k2)来实现,其中k2>L[j];通过循环调用即可找到b[40][40]中的所有尾随后缀,最后再将他们分别存放在b[40][40]中;即通过

for(i=0;i

{

for(j=0;j

{

k2=strlen(b[j]);

if(k2>L[i])

{

Hz(a[i],b[j],L[i],k2);

}

}

}

6)在反复调用Hz(a[i],a[j],L[i],L[j])函数中如果b[40][40]中有重复出现的,即尾随后缀相同的不用再次放入b[40][40]中。

7)在调用函数中所需要注意的问题就是一个比较的问题,也就是实现6)中所提到的。

五.测试结果

5.1、测试数据为0101100111010111101

5.2、测试数据为110111000010

五、源代码

#include

#include

charb[40][40];

intQ;

voidHz(charc[],chard[],intL1,intL2)

{

inti,j,temp=0;

charm[50];

for(i=0;i

{

if(c[i]==d[i])continue;

elsebreak;

}

if(i==L1)

{

for(j=0;j

m[j]=d[L1+j];

m[j]='\0';

for(i=0;i

{

if(strcmp(b[i],m)==0)

{

temp=1;

break;

}

}

if(temp!

=1)

{

strcpy(b[Q],m);

Q++;

}

}

}

voidmain()

{

inti,j,k,k1,k2,n;

chara[40][40];

intL[50];

inttemp=1;

intf=0;

printf("请输入码字个数:

");

scanf("%d",&n);

printf("请分别输入码字:

");

for(i=0;i

{

scanf("%s",&a[i]);

L[i]=strlen(a[i]);

}

for(i=0;i

{

for(j=0;j

{

if(i!

=j&&L[i]

Hz(a[i],a[j],L[i],L[j]);

}

}

 

if(Q>0)

{

for(i=0;i

{

k1=strlen(b[i]);

for(j=0;j

{

if(k1

Hz(b[i],a[j],k1,L[j]);

}

for(k=0;k

{

for(j=0;j

{

k2=strlen(b[j]);

if(k2>L[k])

{

Hz(a[k],b[j],L[k],k2);

}

}

}

}

printf("尾随后缀集合为:

");

for(i=0;i

printf("%s",b[i]);

for(i=0;i

=0;i++)

{

for(j=0;j

{

if(strcmp(a[i],b[j])==0)

{

temp=0;

break;

}

elsecontinue;

}

}

printf("\n");

if(temp==0)printf("该码不是唯一可译码!

\n");

elseprintf("该码是唯一可译码!

\n");

}

elseprintf("该码组是唯一可译码!

");

f++;

printf("\n");

}

题目二:

哈夫曼编码

1课题描述

在这个信息量爆炸的时代,凡是能载荷一定信息量,且码字的平均长度最短,可分离的变长码的码字集合称为最佳变长码。

为此,必须将概率大的信息符号编以短的码字,概率小的符号编以长的码字,使得平均码字最短。

能获得最佳码的编码方法主要有:

香农(Shannon)、费诺(Fano)、哈夫曼(Huffman)编码等。

哈夫曼(Huffman)编码是一种常用的压缩编码方法,是Huffman于1952年为压缩文本文件建立的。

它的基本原理是频繁使用的数据用较短的代码代替,较少使用的数据用较长的代码代替,每个数据的代码各不相同。

哈夫曼压缩是个无损的压缩算法,一般用来压缩文本和程序文件。

哈夫曼压缩属于可变代码长度算法一族。

意思是个体符号用一个特定长度的位序列替代。

因此,在文件中出现频率高的符号,使用短的位序列,而那些很少出现的符号,则用较长的位序列。

哈夫曼编码是哈夫曼树的一个应用,是一种最优的前缀技术,然而其存在的不足却制约了它的直接应用。

首先,其解码时间为O(lavg),其中lavg为码字的平均长度;其次,更为重要的是,解码器需要知道哈夫曼编码树的结构,因而编码器必须为解码器保存或传输哈夫曼编码树。

对于小量数据的压缩而言,这是很大的开销。

因而,应用哈夫曼编码的关键是如何降低哈夫曼编码树的存储空间。

目前流行的很多压缩方法都是用了该技术,如GZIB、ZLIB、PNC等。

2设计原理

对于多进制哈夫曼编码,为了提高编码效率,就要是长码的符号数量尽量少、概率尽量小,所以信源符号数量最好满足n=(m-1)*k+r,其中m为进制数,k为缩减的次数。

设计步骤如下:

[1]将信源符号按概率从大到小的顺序排列,令

p(x1)≥p(x2)≥…≥p(xn)

[2]给两个概率最小的信源符号p(xn-1)和p(xn)各分配一个码位“0”和“1”,将这两个信源符号合并成一个新符号,并用这两个最小的概率之和作为新符号的概率,或者在新添加一个信源符号,令其概率为0,则个分配一个码位“0”、“1”和“2”,将其合并,结果得到一个只包含(n-1)个信源符号的新信源。

称为信源的第一次缩减信源,用S1表示。

[3]将缩减信源S1的符号仍按概率从大到小顺序排列,此后每次合并3个信源符号,得到只含(n-3)个符号的缩减信源S2。

[4]重复上述步骤,直至最后,此时所剩符号的概率之和必为1。

然后从最后一级缩减信源开始,依编码路径向前返回,就得到各信源符号所对应的码字。

3设计过程

3.1软件介绍

3.1.1VisualC++6.0简介

VisualC++6.0,简称VC或者VC6.0,是微软推出的一款C++编译器,将“高级语言”翻译为“机器语言(低级语言)”的程序。

VisualC++是一个功能强大的可视化软件开发工具。

自1993年Microsoft公司推出VisualC++1.0后,随着其新版本的不断问世,VisualC++已成为专业程序员进行软件开发的首选工具。

VisualC++6.0由Microsoft开发,它不仅是一个C++编译器,而且是一个基于Windows操作系统的可视化集成开发环境(integrateddevelopmentenvironment,IDE)。

VisualC++6.0由许多组件组成,包括编辑器、调试器以及程序向导AppWizard、类向导ClassWizard等开发工具。

这些组件通过一个名为DeveloperStudio的组件集成为和谐的开发环境。

Microsoft的主力软件产品。

VisualC++是一个功能强大的可视化软件开发工具。

VisualC++6.0以拥有“语法高亮”,自动编译功能以及高级除错功能而著称。

比如,它允许用户进行远程调试,单步执行等。

还有允许用户在调试期间重新编译被修改的代码,而不必重新启动正在调试的程序。

其编译及创建预编译头文件(stdafx.h)、最小重建功能及累加连结(link)著称。

这些特征明显缩短程序编辑、编译及连结的时间花费,在大型软件计划上尤其显著。

3.1.2主要部分

[1]DeveloperStudio

  

图1DeveloperStudio环境

这是一个集成开发环境,我们日常工作的99%都是在它上面完成的,再加上它的标题赫然写着“MicrosoftVisualC++”,所以很多人理所当然的认为,那就是VisualC++了。

其实不然,虽然DeveloperStudio提供了一个很好的编辑器和很多Wizard,但实际上它没有任何编译和链接程序的功能,真正完成这些工作的幕后英雄后面会介绍。

我们也知道,DeveloperStudio并不是专门用于VC的,它也同样用于VB,VJ,VID等VisualStudio家族的其他同胞兄弟。

所以不要把DeveloperStudio当成VisualC++,它充其量只是VisualC++的一个壳子而已。

这一点请切记!

[2]MFC

从理论上来讲,MFC也不是专用于VisualC++,BorlandC++,C++Builder和SymantecC++同样可以处理MFC。

同时,用VisualC++编写代码也并不意味着一定要用MFC,只要愿意,用VisualC++来编写SDK程序,或者使用STL,ATL,一样没有限制。

不过,VisualC++本来就是为MFC打造的,VisualC++中的许多特征和语言扩展也是为MFC而设计的,所以用VisualC++而不用MFC就等于抛弃了VisualC++中很大的一部分功能。

但是,VisualC++也不等于MFC。

[3]PlatformSDK

这才是VisualC++和整个VisualStudio的精华和灵魂,虽然我们很少能直接接触到它。

大致说来,PlatformSDK是以MicrosoftC/C++编译器为核心(不是VisualC++,看清楚了),配合MASM,辅以其他一些工具和文档资料。

上面说到DeveloperStudio没有编译程序的功能,那么这项工作是由谁来完成的呢?

是CL,是NMAKE,和其他许许多多命令行程序,这些我们看不到的程序才是构成VisualStudio的基石。

3.2设计内容

例:

对如下单符号离散无记忆信源编三进制哈夫曼码。

这里:

m=3,n=8

令k=3,m+k(m-1)=9,则s=9-n=9-8=1

所以第一次取m-s=2个符号进行编码。

由计算可得:

平均码长为:

(3.1)

信息率为:

(3.2)

编码效率为:

(3.3)

可见:

哈夫曼的编码效率相当高,对编码器的要求也简单得多。

编码过程如下:

表1哈夫曼编码

信源

符号

概率

缩减信源

码字

码长

0.4

0.09

0

1

0

0.22

2

0

1

2

1

01.0

1

2

0

1

0.18

10

2

0.1

11

2

0.1

12

2

0.07

21

2

0.06

22

2

0.05

200

3

0.04

201

3

2

 

图2哈夫曼编码

4编码程序及其分析//**哈夫曼编码**

#include"stdio.h"

#include"iostream.h"

#include"math.h"

#defineMaxNo100

typedefcharElemType;

typedefstruct

{

ElemTypedata[MaxNo];

doubleweight;/*信源概率*/

intparent,lchild,rchild;/*父亲和左右孩子节点*/

}HTNode;

typedefstruct

{

charcd[MaxNo];/*存放编码用*/

intstart;

}HCode;

voidCreateHCode(HTNodeht[],HCodehcd[],intn)/*哈夫曼编码子程序*/

{

inti,f,c;

intchoose;

HCodehc;

printf("请输入0或1进行编码方式选择:

");/*方式选择*/

scanf("%d",&choose);

for(i=0;i

{

hc.start=n;c=i;

f=ht[i].parent;

if(choose==0)/*若选择0,则哈夫曼编码以先标0开始*/

{

while(f!

=-1)

{

if(ht[f].lchild==c)hc.cd[hc.start--]='0';

elsehc.cd[hc.start--]='1';

c=f;f=ht[f].parent;

}

hc.start++;

hcd[i]=hc;

}

else/*反之以先标1开始*/

{

{

while(f!

=-1)

{

if(ht[f].lchild==c)hc.cd[hc.start--]='1';

elsehc.cd[hc.start--]='0';

c=f;f=ht[f].parent;

}

hc.start++;

hcd[i]=hc;

}

}

}

}

voidCreateHT(HTNodeht[],intn)/*构造哈夫曼树子程序*/

{

inti,j,k;

ints1,s2;/*节点*/

doublemin1,min2;

for(i=0;i<2*n-1;i++)/*进行2*n-1次合并*/

ht[i].parent=ht[i].lchild=ht[i].rchild=-1;

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

{

min1=min2=32767;

s1=s2=-1;

for(k=0;k<=i-1;k++)/*不断循环组合最终生成Huffman树*/

{

if(ht[k].parent==-1)

{

if(ht[k].weight

{

min2=min1;

s2=s1;

min1=ht[k].weight;

s1=k;

}

elseif(ht[k].weight

{

min2=ht[k].weight;

s2=k;

}

}

}

ht[i].weight=ht[s1].weight+ht[s2].weight;

/*组合树根节点权重为左右子之和*/

ht[i].lchild=s1;

ht[i].rchild=s2;/*组合树左右子分别为s1,s2*/

ht[s1].parent=ht[s2].parent=i;/*新树加入数组*/

}

}

intmain()

{

inti,j,n;

doubleaverage_length,sum=0;

HTNodeht[MaxNo];

HCodehcd[MaxNo];

floatD[100];/*各概率的对数*/

floatH=0.00;

floath[100];/*存放信息熵*/

floatR;/*编码效率*/

cout<<"姓名:

时旭东学号:

311008002320"<

cout<<"请输入信源符号个数:

"<

while(scanf("%d",&n))

{

cout<<"请输入各个信源符号及其概率,比如:

A0.12:

"<

for(i=0;i

{

scanf("%s%lf",&ht[i].data,&ht[i].weight);

sum=ht[i].weight+sum;

}

if(sum>1)/*避免总概率大于1*/

cout<<"概率大于1,请重新输入"<

for(i=0;i

{

D[i]=3.322*(-log10(ht[i].weight));

h[i]=ht[i].weight*D[i];/*各信源的熵*/

H=H+h[i];

}

CreateHT(ht,n);/*生成哈夫曼树*/

CreateHCode(ht,hcd,n);/*生成哈夫曼编码*/

cout<<"哈夫曼编码如下:

"<

for(i=0;i

{

printf("%s:

",ht[i].data);

for(j=hcd[i].start;j<=n;j++)

printf("%c",hcd[i].cd[j]);

printf("\n");

}

cout<<"下面将计算该码的平均码长、编码效率:

"<

average_length=0;

for(i=0;i

average_length+=ht[i].weight*(n-hcd[i].start+1);

/*计算该信源的平均码长*/

cout<<"平均编码长度:

K="<

R=H/average_length;/*编码效率*/

cout<<"编码效率:

R="<

}

return0;

}

2.截图

图3程序运行结果

 

总结

在这次课程设计中,通过对程序的编写,调试和运行,使我更好的掌握了Huffman树等数据结构方面的基本知识和各类基本程序问题的解决方法,熟悉了各种调用的数据类型,在调试和运行过程中,加深我对程序运行的环境了解和熟悉的程度,同时也提高了我对程序调试分析的能力和对错误纠正的能力。

这次信息论与编码的程序设计,对于我来说是一个挑战。

我对数据结构的学习在程序的设计中也有所体现。

课程设计是培养学生综合运用所学知识,发现问题、提出问题、分析问题和解决问题的过程,锻炼学生的逻辑思维能力和实践能力,是对学生实际工作能力的具体训练和考察过程。

在整个课程程序中,我们充分应用和调用各个程序模块,从而部分实现了此次程序设计的所应该有的功能。

就是我在课程设计是比较成功的方面,而

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

当前位置:首页 > 小学教育 > 学科竞赛

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

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