不确定有穷状态自动机的确定化实验报告_第1页
不确定有穷状态自动机的确定化实验报告_第2页
不确定有穷状态自动机的确定化实验报告_第3页
不确定有穷状态自动机的确定化实验报告_第4页
不确定有穷状态自动机的确定化实验报告_第5页
已阅读5页,还剩3页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、编译原理实验报告(二) E01214055 鲁庆河1. 实验名称:不确定有穷状态自动机的确定化2. 实验目的:a) 输入:非确定有穷状态自动机NFA b) 输出:确定化的有穷状态自动机DFA3. 实验原理:a) NFA确定化为DFA同一个字符串可以由多条通路产生,而在实际应用中,作为描述控制过程的自动机,通常都是确定有限自动机DFA,因此这就需要将不确定有限自动机转换成等价的确定有限自动机,这个过程称为不确定有限自动机的确定化,即NFA确定化为DFA。b) NFA的确定化算法 - 子集法:l 若NFA的全部初态为S1,S2,Sn,则令DFA的初态为:SS1,S2,Sn, 其中方括号用来表示若干

2、个状态构成的某一状态。l 设DFA的状态集K中有一状态为Si,Si+1,Sj,若对某符号a,在NFA中有F( Si,Si+1,Sj ,a)= Si,Si+1,Sk ,则令F( Si,Si+1,Sj ,a)= Si,Si+1,Sk 为DFA的一个转换函数。若 Si,Si+1,Sk 不在K中,则将其作为新的状态加入到K中。l 重复第2步,直到K中不再有新的状态加入为止。l 上面得到的所有状态构成DFA的状态集K,转换函数构成DFA的F,DFA的字母表仍然是NFA的字母表。l DFA中凡是含有NFA终态的状态都是DFA的终态。c) closure(I)函数,move(I,a)函数的假设I是NFA M

3、状态集K的一个子集(即IK),则定义-closure(I)为:1. 若QI,则Q-closure(I);2. 若QI,则从Q出发经过任意条弧而能到达的任何状态Q,则Qclosure(I)。3. 状态集-closure(I)称为状态I的闭包。假设NFA M( K,F,S,Z ),若IK,a,则定义Iaclosure(J),其中J是所有从closure(I)出发,经过一条a弧而到达的状态集。 NFA确定化的实质是以原有状态集上的子集作为DFA上的一个状态,将原状态间的转换为该子集间的转换,从而把不确定有限自动机确定化。经过确定化后,状态数可能增加,而且可能出现一些等价状态,这时就需要简化。4. 实

4、验思路:(数据结构及变量设计等) 5. 实验小结:在写此次试验之初,数据结构设计是这样的,K,E,S,Z都用一位字符数组存储,F用下面的链表存储,但是最终在写move函数时查找J集合麻烦,加之数据结构算法的实现基本功不够,在同学的指点下就从新定义了数据结构。在新的数据结构中,使用邻接表来存储转换函数的,虽然数据结构部分对于顺序表 链表 邻接表的操作很陌生,但通过此次的实验让我对于数据结构中邻接表的使用有了很好的复习和回顾,也学会了邻接表中指针的使用和插入删除操作此次实验过程中,代码虽然全部都是本人自己编写,但很多不是我自己的思想,是从同学那剽窃来理解消化的,在别人和我讲述了代码之后,我自己独立

5、的去写时,细节的地方仍然是漏洞百出,到处出错。我的代码能力太差,也常常因为这而自卑,但也不知如何去提升,虽然课本上的确定化会写,算法也能够理解和掌握,但是实现起来就是无从下手,所以动手能力差的同时,书本知识也得不到强化。 我会借编译原理实验的机会慢慢的熟悉代码,自己去想通算法,自己去实现算法。我很感激姚老师的严厉要求,我相信我们院的老师都要像您和王爱平老师这样的就好了!6. 附件:(程序和运行结果截图)a) 程序:#include <stdlib.h>#include <malloc.h>#include <stdio.h>#include <coni

6、o.h>#define N 20 /用于控制数组的最大长度/用邻接表存储NFA和DFA的状态 字母 后继typedef struct adjvex/定义邻接表的邻接点域的数据表示char nextstate;/头结点状态的后继状态char arc;/弧struct adjvex *next;/指向该头结点状态的下一个后继状态的指针adjvex;typedef struct headvex/定义邻接表的头部的数据表示char state;/状态adjvex *firstarc;/指向第一个后继状态的指针headvex;/定义两个邻接表的头部,为全局数组headvex NFAN;/用邻接表存

7、储的NFAheadvex DFAN;/用邻接表存储的DFAchar AlpN;/存储需要输入的行为集,即字母表void main()void designby();/函数声明void closure(char s,char setN);/求e_closure闭包函数void Special(char DFA_startN,char new_stateNN);/确定化函数designby();int i,j;char NFA_startN;/存放NFA的初态char DFA_startN;/存放DFA的初态char NFA_finalN;/存放NFA的终态char DFA_finalN;/存放D

8、FA的终态char new_stateNN;/存放DFA的I的二维数组 每一行为一个原NFA的一个新的状态集,e-closure(move(I,a)for(i=0; i<N; i+)NFAi.state='#'NFAi.firstarc=NULL;DFAi.state='#'DFAi.firstarc=NULL;Alpi='#'NFA_starti='#'DFA_starti='#'NFA_finali='#'DFA_finali='#'for(j=0; j<N; j+)

9、new_stateij='#'int m,n;printf("请输入NFA: 状态的个数: bbb");scanf("%d",&n);fflush(stdin);printf(" 状态转换个数: bbb");scanf("%d",&m);fflush(stdin);printf("请输入各状态:(状态,0/1/2),终态输2,非初终态输1,初态输0.n");/创建邻接表int f;for(i=0; i<n; i+)/n个状态的输入,依次存储到已开辟空间的邻接

10、表头结点中,并根据状态分类装入NFA的初态终态数组中.printf("状态%d:",i+1);scanf("%c,%d",&NFAi.state,&f);fflush(stdin);if(f=0)/输入状态若为初态,依次存入到NFA_startN数组中for(j=0; j<N && NFA_startj!='#'j+);NFA_startj=NFAi.state;if(f=2)/输入状态若为终态,依次存入到NFA_finalN数组中for(j=0; j<N && NFA_fina

11、lj!='#'j+);NFA_finalj=NFAi.state;printf("输入完毕!nn");printf("请输入状态转换函数:(状态1,状态2,输入字符)n");adjvex *p;/定义一个指向adjvex的指针pchar from,to,arc;int k;for(i=0; i<m; i+)/m个转换函数的输入,开辟空间并依次存储至相应头结点状态的邻接表中.printf("状态转换%d:",i+1);scanf("%c,%c,%c",&from,&to,&

12、;arc);fflush(stdin);p=(adjvex *)malloc(sizeof(adjvex);p->nextstate=to;p->arc=arc;for(k=0; NFAk.state!=from; k+);/结束时k的值即为匹配状态所在的头结点p->next=NFAk.firstarc;/前插法插入结点到头结点后NFAk.firstarc=p;/前插法插入结点到头结点后if(arc!='$')/输入字符不为空,保存到AlpsN字母表中for(j=0; j<N && Alpj!='#'j+)if(arc=A

13、lpj)break;/存在则跳出,结束不保存/上循环结束的两个可能: 1、该输入字符已经存在于字母表中 不存跳出,则下面的if也不会成立;/2、从0开始到#结束都没找不到一样的字母,结束for,记下了j.if(Alpj='#') Alpj=arc;printf("输入完毕!nn");/求所有NFA_startN中所有初态的closure形成总的初态DFA_startN/char startNN;/for(i=0; i<N; i+)/for(j=0; j<N; j+)/startij='#'/for(i=0; NFA_starti!

14、='#' i+)/依次对每个NFA初态求等价状态放在二维数组中/closure(NFA_starti,DFA_start);/*int k;for(i=0; NFA_starti!='#' i+)/将start二维数组变到一位数组DFA_startN中for(j=0; startij!='#' j+)k=0;for(k=0;DFA_startk!=startij && DFA_startk!='#'k+);if(DFA_startk='#')DFA_startk=startij;else conti

15、nue;*/k=0;while(NFAk.state!=NFA_start0)k+;closure(NFAk.state,DFA_start);/求初态的e_closure闭包/for(int z=0; z<N; z+)/printf("%4c %4cn",NFA_startz,DFA_startz);Special(DFA_start,new_state);/有DFA_startN,即为new_state0通过对NFAN邻接表依次求/for(z=0; z<N; z+)/printf("%sn",new_statez);/k=0;for(i=

16、0;i<N&&new_statei0!='#'i+)/寻找DFA的终态for(j=0;j<N&&new_stateij!='#'j+)for(f=0;f<N&&NFA_finalf!='#'f+)if(new_stateij=NFA_finalf)DFA_finalk=i+65;k+;break;if(new_stateij=NFA_finalf)break;/NFA和DFA的输出:k=0;for(i=0;i<N&&new_statei0!='#

17、9;i+)/寻找DFA的终态for(j=0;j<N&&new_stateij!='#'j+)for(f=0;f<N&&NFA_finalf!='#'f+)if(new_stateij=NFA_finalf)DFA_finalk=i+65;k+;break;if(new_stateij=NFA_finalf)break;printf("确定化后的DFA如下所示:n");printf(" ");for(i=0;Alpi!='#'i+)printf("%3c&

18、quot;,Alpi); printf(" 初终");printf("n");for(i=0;DFAi.state!='#'i+)/以矩阵形式输出DFAprintf("%4c",DFAi.state);for(j=0;Alpj!='#'j+)p=DFAi.firstarc;while(p)if(p->arc=Alpj)printf("%3c",p->nextstate);break;elsep=p->next;if(p=NULL)printf(" &quo

19、t;);for(k=0;k<N&&DFA_finalk!='#'k+)if(DFAi.state=DFA_finalk)break;if(DFA_finalk='#')printf(" 0");elseprintf(" 1");printf("n");printf("每个新的状态对应的原状态子集如下:n");/输出对应的NFA子集for(i=0;i<N&&new_statei0!='#'i+)printf("%3c

20、",i+65);printf(" ");for(j=0;j<N&&new_stateij+1!='#'j+)printf("%c,",new_stateij);printf("%c",new_stateij);printf("n");printf("新的终态如下:n");for(i=0;i<N&&DFA_finali!='#'i+)printf("%3c",DFA_finali);print

21、f("n");void closure(char s,char setN)/找一个状态s经过任意连续个的空弧所到达的等价状态的集合setN(包括自身即为0条空弧)int i,j;for(i=0;seti!='#'i+)/将自身存储到setN中,0条空弧if(seti=s)break;if(seti='#')seti=s;for(j=0;NFAj.state!=s;j+);/查找相应状态所在的邻接表的头结点状态位置jadjvex *p;p=NFAj.firstarc;/指针p指向该头结点状态的第一个后继状态while(p)if(p->ar

22、c='$')closure(p->nextstate,set);/若为空弧的话,递归进入该后继状态所对应的头结点状态处依次查找其空弧后继,查找结束回到上一层后继状态继续查找p=p->next;elsep=p->next;/查看该头结点状态的下一个后继状态return;void move(char FromN,char arc,char ToN)/找一个状态集FromN的所有状态的arc后继状态的集合ToNint i,j,k,t=0;adjvex *p;j=0;/首先定义j为0for(i=0; i<N && Fromi!='#

23、9;i+ )/依次对其中的每一个状态求move,直至结束for(k=0;NFAk.state!=Fromi;k+);/查找相应状态所在的邻接表的头结点状态位置jp=NFAk.firstarc;/指针p指向该头结点状态的第一个后继状态while(p)/逐个后继状态往后判断后继结束,每次将弧为arc的状态保存到ToN中if(p->arc=arc)for(k=0; k<N && Tok!='#' k+)if(Tok=p->nextstate)p=p->next;break;/该状态若已存在ToN中,跳出循环不保存,移动指针查看下一个后继状态if

24、(Tok='#')/直达结束没有发现已经存入,Tot+=p->nextstate;p=p->next;else p=p->next;void Order(char aN)/由小到大对数组中的每个字符排序int i,j;char temp;for(i=0;i<N&&ai!='#'i+)for(j=i+1;j<N&&aj!='#'j+)if(aj<ai)temp=ai;ai=aj;aj=temp;void Special(char DFA_startN,char new_stateN

25、N)int i,j;char To1N,To2N;char order1N,order2N;for(i=0; i<N; i+)To1i='#'To2i='#'for(i=0; i<N && DFA_starti!='#'i+)new_state0i=DFA_starti;/将DFA_startN复制到new_state0,作为一个状态int st,k,t;adjvex *p;for(st=0; st<N && new_statest0!='#' st+ )DFAst.state=st+65;for(i=0; Alpi!='#' i+)for(k=0; k<N; k+)To1k='#' To2k='#'/每次使用TO1,To2都要清除原有数据move(new_statest,Alpi,To1);for(j=0;To1j!='#'j+)/循环求状态集的closure闭包(求每一个状态的closure时,都会对上一个状态得到的To2N从头找不相同的存进去)closure(To1j,To2);for(j=0; j<N&&new_statej0!='#' j+)/将

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论