《不确定有穷状态自动机的确定化实验报告》由会员分享,可在线阅读,更多相关《不确定有穷状态自动机的确定化实验报告(8页珍藏版)》请在金锄头文库上搜索。
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 #include #include #include #define N 20 /用于控制数组的最大长度/用邻接表存储NFA和DFA的状态 字母 后继typedef
6、 struct adjvex/定义邻接表的邻接点域的数据表示char nextstate;/头结点状态的后继状态char arc;/弧struct adjvex *next;/指向该头结点状态的下一个后继状态的指针adjvex;typedef struct headvex/定义邻接表的头部的数据表示char state;/状态adjvex *firstarc;/指向第一个后继状态的指针headvex;/定义两个邻接表的头部,为全局数组headvex NFAN;/用邻接表存储的NFAheadvex DFAN;/用邻接表存储的DFAchar AlpN;/存储需要输入的行为集,即字母表void ma
7、in()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;/存放DFA的终态char new_stateNN;/存放DFA的I的二维数组 每一行为一个原NFA的一个新的状态集,e-closu
8、re(move(I,a)for(i=0; iN; i+)NFAi.state=#;NFAi.firstarc=NULL;DFAi.state=#;DFAi.firstarc=NULL;Alpi=#;NFA_starti=#;DFA_starti=#;NFA_finali=#;DFA_finali=#;for(j=0; jN; j+)new_stateij=#;int m,n;printf(请输入NFA: 状态的个数: bbb);scanf(%d,&n);fflush(stdin);printf( 状态转换个数: bbb);scanf(%d,&m);fflush(stdin);printf(请输
9、入各状态:(状态,0/1/2),终态输2,非初终态输1,初态输0.n);/创建邻接表int f;for(i=0; in; i+)/n个状态的输入,依次存储到已开辟空间的邻接表头结点中,并根据状态分类装入NFA的初态终态数组中.printf(状态%d:,i+1);scanf(%c,%d,&NFAi.state,&f);fflush(stdin);if(f=0)/输入状态若为初态,依次存入到NFA_startN数组中for(j=0; jN & NFA_startj!=#;j+);NFA_startj=NFAi.state;if(f=2)/输入状态若为终态,依次存入到NFA_finalN数组中for
10、(j=0; jN & NFA_finalj!=#;j+);NFA_finalj=NFAi.state;printf(输入完毕!nn);printf(请输入状态转换函数:(状态1,状态2,输入字符)n);adjvex *p;/定义一个指向adjvex的指针pchar from,to,arc;int k;for(i=0; inextstate=to;p-arc=arc;for(k=0; NFAk.state!=from; k+);/结束时k的值即为匹配状态所在的头结点p-next=NFAk.firstarc;/前插法插入结点到头结点后NFAk.firstarc=p;/前插法插入结点到头结点后if(
11、arc!=$)/输入字符不为空,保存到AlpsN字母表中for(j=0; jN & Alpj!=#;j+)if(arc=Alpj)break;/存在则跳出,结束不保存/上循环结束的两个可能: 1、该输入字符已经存在于字母表中 不存跳出,则下面的if也不会成立;/2、从0开始到#结束都没找不到一样的字母,结束for,记下了j.if(Alpj=#) Alpj=arc;printf(输入完毕!nn);/求所有NFA_startN中所有初态的closure形成总的初态DFA_startN/char startNN;/for(i=0; iN; i+)/for(j=0; jN; j+)/startij=#
12、;/for(i=0; NFA_starti!=#; 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 continue;*/k=0;while(NFAk.state!=NFA_start0)k+;closure(NFAk.state,DFA_start);/求初态的e_closure闭包/for(int z=0; zN; z+)/printf(%4c %4cn,NFA_startz,DFA_startz);Special(DFA_start,new_state);/有DFA_startN,即为new_state0通过对NFAN邻接表依次求/for(z=0; zN; z+)/printf(%sn,new_statez);/k=0;for(i=0