实验2 唯一可译码判决准则.docx

上传人:b****5 文档编号:12181810 上传时间:2023-04-17 格式:DOCX 页数:14 大小:55.90KB
下载 相关 举报
实验2 唯一可译码判决准则.docx_第1页
第1页 / 共14页
实验2 唯一可译码判决准则.docx_第2页
第2页 / 共14页
实验2 唯一可译码判决准则.docx_第3页
第3页 / 共14页
实验2 唯一可译码判决准则.docx_第4页
第4页 / 共14页
实验2 唯一可译码判决准则.docx_第5页
第5页 / 共14页
点击查看更多>>
下载资源
资源描述

实验2 唯一可译码判决准则.docx

《实验2 唯一可译码判决准则.docx》由会员分享,可在线阅读,更多相关《实验2 唯一可译码判决准则.docx(14页珍藏版)》请在冰豆网上搜索。

实验2 唯一可译码判决准则.docx

实验2唯一可译码判决准则

实验二唯一可译码判决准则

一、实验目的

(1)进一步熟悉唯一可译码判决准则;

(2)掌握C语言字符串处理程序的设计和调试技术。

二、实验要求

(1)已知:

信源符号个数q、码字集合C。

(2)输入:

任意的一个码。

码字个数和每个具体的码字在运行时从键盘输入。

(3)输出:

判决(是唯一可译码/不是唯一可译码)。

三、算法

1.考察C中所有的字码,若

的前缀,则将相应的后缀作为一个尾随后缀码放入集合

中;

2.考察C和

两个集合,若

的前缀或

的前缀,则将相应的后缀作为尾随后码放入集合

3.

即为码C的尾随后缀集合;

4.若

中出现了

中的元素,则算法终止,返回假(

不是唯一可译码);否则,若

中没有出现新的元素,则返回真。

四、代码

#include

#include

#include

#include

usingnamespacestd;

#defineISSAME0

#defineISPREFIX1

#defineNOTPREFIX2

#defineISUDC0//唯一可译码

#defineISRTC1//即时码

#defineNOTUDC2//非唯一可译码

typedefvectorpCharVector;

/**//*判断chPrefix是否为chWord的前缀.*/

intIsPrefix(constchar*chPrefix,constchar*chWord);

/**//*往后缀码集合中插入不重复的键,*/

boolPushBackUniqueValue(pCharVector&pCode,char*pValue);

/**//*判断码字序列的类型,非回溯法*/

intIsUDC(constpCharVector&pCode);

/**//*回溯计算,如果不是唯一可译码则可以得到一串有歧义的码字序列(即有多种译法的

/*序列),该序列用参数中的pInvalidSeqBuf返回,调用者需记得释放内存

/*该方法的缺点是没有检测码字序列中是否有重复码字*/

intIsUDC_Backtrace(constpCharVector&pCode,char**pInvalidSeqBuf);

//#defineTEST_BY_FILE

intmain()

{

#ifdefTEST_BY_FILE

freopen("in","r",stdin);//文件重定向freopen函数,文本多行读入*freopen(char*filename,char*type,FILE*stream)

#endif

pCharVectorVCode;

intnCodeNum;

inti;

charchContinue;

do

{

cout<<"请输入信源编码个数:

";

cin>>nCodeNum;

cout<<"请输入依次"<

";

for(i=0;i

{

//将输入读取到缓冲区

stringstrBuffer;

cin>>strBuffer;

//copy字符到动态数组中已进行比较

char*pTemp=newchar[strBuffer.size()+1];

//*memcpy(void*dest,void*src,unsignedintcount),功能:

由src所指内存区域复制count个字节到dest所指内存区域

//src和dest所指内存区域不能重叠,函数返回指向dest的指针

memcpy(pTemp,strBuffer.c_str(),sizeof(char)*(strBuffer.size()+1));//c_str()是把string转化为char*型

VCode.push_back(pTemp);//push_back()函数会在vector对象VCode后面添加元素

}

char*pRetn=NULL;

intnRetn=IsUDC_Backtrace(VCode,&pRetn);

if(NOTUDC!

=nRetn)

{

cout<<"该码字序列/集合是唯一可译码!

"<

}

else

{

cout<<"该码字序列/集合不是唯一可译码!

"<

cout<<"有歧义序列为:

"<

}

//清除内存

delete[]pRetn;

for(i=0;i

{

delete[]VCode.at(i);//AT()函数:

返回一个字符表达式或备注字段在另一个字符表达或备注字段中首次出现的位置,

//从最左边开始计数。

}

VCode.clear();//清除VCode流

cout<<"继续吗?

(Y/N):

";

cin>>chContinue;

}while(toupper(chContinue)=='Y');//toupper(将小写字母转换成大写字母)

#ifdefTEST_BY_FILE

fclose(stdin);//fclose是关闭freopen()的指针

#endif

return0;

}

intIsPrefix(constchar*chPrefix,constchar*chWord)

{

assert(chPrefix!

=NULL&&chWord!

=NULL);

intnLenPrefix,nLenWord;

nLenPrefix=strlen(chPrefix);

nLenWord=strlen(chWord);

//前缀长度大于整个词的长度,返回false

if(nLenPrefix>nLenWord)

{

returnNOTPREFIX;

}

intnRetn=memcmp(chPrefix,chWord,sizeof(char)*strlen(chPrefix));

if(0==nRetn&&nLenPrefix==nLenWord)returnISSAME;

if(0==nRetn)returnISPREFIX;

returnNOTPREFIX;

}

boolPushBackUniqueValue(pCharVector&pCode,char*pValue)

{

assert(pValue!

=NULL);

for(inti=0;i

{

if(0==strcmp(pValue,pCode[i]))//有重复,直接返回

returnfalse;

}

pCode.push_back(pValue);

returntrue;

}

intIsUDC(constpCharVector&pCode)

{

assert(pCode.size()!

=0);

//用于存放后缀码

pCharVectorCodePostfix;

//第一轮比较,码字内部比较,得到第一个后缀码集合

char*iter1,*iter2;

inti,j;

for(i=0;i

{

iter1=pCode.at(i);

for(j=0;j

{

//不比较自身

if(i==j)continue;

iter2=pCode.at(j);

intnRetn=IsPrefix(iter1,iter2);

if(ISSAME==nRetn)returnNOTUDC;

if(ISPREFIX==nRetn)

{

//将iter2的后缀填入CodePostfix

PushBackUniqueValue(CodePostfix,iter2+strlen(iter1));

}

}

}

if(CodePostfix.size()==0)returnISRTC;

//第二轮比较,比较后缀码集合中是否含有码字集合中的元素

//有则返回NOTUDC,如果后缀码集合中没有再出现新元素了表明该码字是

//UDC

//指向当前集合在整个后缀码集合中的位置,也即是

//前面所有后缀码的个数

intnPointer=CodePostfix.size();

//指向当前集合的大小

intnNewAssembleSize=nPointer;

do

{

nPointer=CodePostfix.size();

for(i=0;i

{

iter1=pCode.at(i);

for(j=nPointer-nNewAssembleSize;j

{

iter2=CodePostfix.at(j);

intnRetn=IsPrefix(iter1,iter2);

if(nRetn==ISSAME)

{

cout<<"码字"<

";

//两个码字相同,返回false

returnNOTUDC;

}

if(ISPREFIX==nRetn)

{

//将iter2的后缀填入CodePostfixTemp

PushBackUniqueValue(CodePostfix,iter2+strlen(iter1));

}

if(ISPREFIX==IsPrefix(iter2,iter1))

{

//将iter1的后缀填入CodePostfixTemp

PushBackUniqueValue(CodePostfix,iter1+strlen(iter2));

}

}

}

nNewAssembleSize=CodePostfix.size()-nPointer;

}while(nNewAssembleSize!

=0);

CodePostfix.clear();

returnISUDC;

}

/**//*该函数是用来对每个pPostfix和原码字序列进行比较,如果重复了则在pRetnBuf中

/*返回本身.并返回1.否则如果没有得到新的后缀码的话返回0表示无重复*/

/**//*Stack用来存储递归中产生的后缀码集合,这样确保每次得到的后缀码不会重复

/*防止进去死循环*/

intGetBacktraceSeq(constpCharVector&pCode,char*pPostfix,pCharVector&Stack,char**pRetnBuf)

{

char*iter1;

for(inti=0;i

{

iter1=pCode.at(i);

intnRetn=IsPrefix(iter1,pPostfix);

if(nRetn==ISSAME)

{

//第一次进来的话由于是码字序列内部的比较,所以

//肯定会遇到自己跟自己比较然后相等的情况,对该情况不允考虑

if(Stack.size()==0)continue;

*pRetnBuf=newchar[strlen(pPostfix)+1];

strcpy(*pRetnBuf,pPostfix);

return1;

}

if(ISPREFIX==nRetn)

{

//新得到的后缀码已经重复了,跳过对他的处理

if(PushBackUniqueValue(Stack,iter1)==false)continue;

char*pTemp=NULL;

//递归处理下一个后缀码

if(GetBacktraceSeq(pCode,pPostfix+strlen(iter1),Stack,&pTemp)==0)

{

*pRetnBuf=NULL;

Stack.pop_back();

continue;

}

Stack.pop_back();

//递归过程中遇到重复码字,算法应立即返回.

//将自身和递归得到的后面的后缀码组合成一个歧义序列返回

char*pNewTraceSeq=newchar[strlen(iter1)+strlen(pTemp)+1];

pNewTraceSeq[0]=0;

strcat(pNewTraceSeq,iter1);

strcat(pNewTraceSeq+strlen(iter1),pTemp);

delete[]pTemp;

*pRetnBuf=pNewTraceSeq;

return1;

}

if(ISPREFIX==IsPrefix(pPostfix,iter1))

{

if(PushBackUniqueValue(Stack,pPostfix)==false)continue;

char*pTemp=NULL;

if(GetBacktraceSeq(pCode,iter1+strlen(pPostfix),Stack,&pTemp)==0)

{

*pRetnBuf=NULL;

Stack.pop_back();

continue;

}

Stack.pop_back();

char*pNewTraceSeq=newchar[strlen(pPostfix)+strlen(pTemp)+1];

pNewTraceSeq[0]=0;

strcat(pNewTraceSeq,pPostfix);

strcat(pNewTraceSeq+strlen(pPostfix),pTemp);

delete[]pTemp;

*pRetnBuf=pNewTraceSeq;

return1;

}

}

return0;

}

/**//*用递归的方法实现唯一可译码的判决,当码字序列不是唯一可译码时,输出有歧义的

/*码字序列*/

intIsUDC_Backtrace(constpCharVector&pCode,char**pInvalidSeqBuf)

{

assert(pCode.size()!

=0);

//用于存放后缀码

pCharVectorCodePostfix;

//第一轮比较,码字内部比较,得到第一个后缀码集合

char*iter1;

inti,j;

pCharVectorStack;

for(i=0;i

{

iter1=pCode.at(i);//AT()函数:

返回一个字符表达式或备注字段在另一个字符表达或备注字段中首次出现的位置,

//从最左边开始计数。

char*pTemp=NULL;

intnRetn=GetBacktraceSeq(pCode,iter1,Stack,&pTemp);

if(nRetn==1)

{

*pInvalidSeqBuf=pTemp;

returnNOTUDC;

}

}

*pInvalidSeqBuf=NULL;

returnISUDC;

}

五、运行结果

1、为唯一可译码时:

(1)已知:

信源符号个数6、码字集合{abaaedeacdbbsdnf}

(2)输入:

任意的一个码。

码字个数和每个具体的码字在运行时从键盘输入。

(3)输出:

判决(是唯一可译码)。

2、不是唯一可译码时:

(1)已知:

信源符号个数6、码字集合{acadabbbadad}

(2)输入:

任意的一个码。

码字个数和每个具体的码字在运行时从键盘输入。

(3)输出:

判决(不是是唯一可译码)。

歧义序列为:

adad

六、实验总结

本实验使用C++编写,使用了递归方法比较出了惟一可译码和不是唯一可译码,感觉这个实验比较复杂,对于信息论与编码也是一个很好的复习,也是对C++语言的一个回顾与熟悉,便于后面的实验。

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

当前位置:首页 > 高中教育 > 高中教育

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

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