编译原理NFA确定化

来源:互联网 发布:i.t是什么牌子 知乎 编辑:程序博客网 时间:2024/05/08 02:22

1,   实验名称

不确定有穷自动机的确定化。

2,   实验目的

不确定有穷自动机的确定化。

3,   实验原理

 

1.NFA:
一个不确定的有穷自动机M是一个五元组,M=(K,E,f,S,Z)其中
a. K是一个有穷集,它的每个元素称为一个状态;
b. E是一个有穷字母表,它的每个元素称为一个输入符号;
c. f是一个从K×E*到K的子集的映像,即:K*E*->2k,其中2k表示K的幂集;
d. S包含于K,是一个非空初态集;
e. Z包含于K,是一个终态集。
2.DFA:
一个确定的有穷自动机M是一个五元组,M=(K,E,f,S,Z)其中
a. K是一个有穷集,它的每个元素称为一个状态;
b. E是一个有穷字母表,它的每个元素称为一个输入符号;
c. f是转换函数,是K×E->K上的映像,即,如f(ki,a)=kj(ki∈K,kj∈K)就意味着,当前状态为ki,输入字符为a时,将转换到下一状态kj,我们把kj称作ki的一个后继状态;
d. S∈K,是唯一的一个初态;
e. Z包含于K,是一个终态集,终态也称可接受状态或结束状态。

     3,正规式

正规式是一种表示正规集的工具,正规式是描述程序语言单词的表达式,对于字母表∑其上的正规式及其表示的正规集可以递归定义如下。

ε是一个正规式,它表示集合L(ε)={ε}

若a是∑上的字符,则a是一个正规式,它所表示的正规集L(a)={a}。

若正规式r和s分别表示正规集L(r)、L(s),则

(a)r|s是正规式,表示集合L(r)L(s)

(b)r·s是正规式,表示集合L(r)L(s);

(c)r*是正规式,表示集合(L(r))*;

(d)(r)是正规式,表示集合L(r)。

仅由有限次地使用上述三个步骤定义的表达式才是∑上的正规式。

运算符“|”、“·”、“*”分别称为“或”、“连接”和“闭包”。在正规式的书写中,连接运算符“·”可省略。运算符的优先级从高到低顺序排列为:“*”、“·”、“|”。

运算符“|”表示“或”、并集。“*”表示*之前括号里的内容出现0次或多次。

若两个正规式表示的正规集相同,则认为二者等价。两个等价的正规集U和V记作U=V。

4.   实验思路

1.状态集合I的空闭包closure(I),定义为一个状态集。

  算法:

遍历I集合中的每一个元素,对于每一元素遍历所有的边,若该元素在NFA中连接到空边,则获取空边另一端的元素,判断元素是否在I中,若不在I中,则加入I,直到遍历结束。

2.确定化

算法:

A.找到NFA的开始符S,对开始符求closure(S),并创建集合T

并T(0)=closure({S})

B.找到T中未被标记的集合T1,若未找到,

C.对T1中,每一元素,执行函数F

D.执行步骤B

函数F:

A.对于T1中的每一元素a,找到每一元素在NFA同一类型的边所对应的元素c,把所有的c都放在集合C中,对于C求C=closure(C)。判断C是否在T中,若不在,则把C加入T。,记录T1->C的边,

B.执行A,知道把所有不同类型的边遍历为止。

3.构造DFA

a.对于集合In,选出集合In的每一I,在I中选出一个元素代表该集合,构造新的DFA

5.   实验小结

  实验算法清晰,简单,只要是对于每一集合反复求closure闭包比较麻烦。程序循环,判断,标志位特别多。很容易出错。对于程序的内存管理更要小心,不要内存越界。

同时,我用的code blocks 编译器问题很大。当程序代码超过一定量、内存分配的数目和空间比较多的时候,对于内存的管理就会出现难以预料的错误。比如在程序开头分配了一段内存,在程序的末尾要使用该内存给其他变量赋值时,就会导致程序崩溃

#include<stdio.h>#include<malloc.h>#include<string.h>char nfa[25][4];    struct list    {        char a[20];         int  b;         char c;         int a_n;    } ;    struct list t[20];    int n; /*number of NFA edage*/int main(){    printf("鉏飞祥E21414018\n");    int cg=3;    printf("请输入每条边和节点\n例如:1a8表示0从1边到8,*代表空边以/结束输出\n");    void closure(int n);    char u[20];    int  ed[20][4];    int n_ed=0;    n=0;    int n_t=0;/*number of T */    int i=0;    int k=1;    int j;    while(1)    {        scanf("%s",nfa[i]);        if(nfa[i][0]=='/')            break;        i++;         n++;    }    t[0].a[0]=nfa[0][0];    for(i=0;i<n;i++)    {        if(nfa[i][0]==nfa[0][0])        {            if(nfa[i][1]=='*')            {                t[0].a[k]=nfa[i][2];                k++;            }        }    }    t[0].a_n=k;    t[0].a[k]='\0';    n_t++;    t[0].b=0;    closure(0);    char temp;    for(i=0;i<n_t;i++)        for(j=0;;j++)        {            if(t[i].a[j]=='\0')                break;        for(k=j+1;;k++)    {        if(t[i].a[k]=='\0')            break;        if(t[i].a[k]<t[i].a[j])        {            temp=t[i].a[k];            t[i].a[k]=t[i].a[j];            t[i].a[j]=temp;        }    }        }    int u_i;    int nn=n_t;    while(1)    {        u_i=0;        int bo=0;        int t_i;        for(t_i=0;t_i<n_t;t_i++)/*judge over*/        {            if(t[t_i].b==0)            {                t[t_i].b=1;                bo++;                break;            }        }        if(bo==0)            break;        char a='a';           int cc=cg; /*有几条不同的边*/        while(cc--)        {            u_i=0;        for(i=0;i<t[t_i].a_n;i++)        {            for(j=0;j<n;j++)            {                if(t[t_i].a[i]==nfa[j][0])                    if(nfa[j][1]==a)                {                int b1=0;                int ii;                for(ii=0;ii<u_i;ii++)                {                    if(u[ii]==nfa[j][2])                        b1=1;                }                if(b1==0)                    u[u_i]=nfa[j][2];                    u_i++;                }            }        }        u[u_i]='\0';        int i,j,k;    for(i=0;i<u_i;i++)        for(j=0;j<n;j++)        {            if(u[i]==nfa[j][0])                if(nfa[j][1]=='*')            {                int b1=0;                int ii;                for(ii=0;ii<u_i;ii++)                {                    if(u[ii]==nfa[j][2])                        b1=1;                }                if(b1==0)                {                u[u_i]=nfa[j][2];                u_i++;                }            }        }        u[u_i]='\0';        char temp;        for(i=0;i<u_i;i++)            for(j=i+1;j<u_i;j++)        {            if(u[j]<u[i])            {                temp=u[j];                u[j]=u[i];                u[i]=temp;            }        }        bo=0;        for(i=0;i<n_t;i++)        {            if(strcmp(u,t[i].a)==0)            {                bo++;                 ed[n_ed][0]=nn-1;            ed[n_ed][1]=(int)a;            ed[n_ed][2]=i;            n_ed++;                break;            }        }        if(bo==0)            if(u_i!=0)        {            strcpy(t[n_t].a,u);            t[n_t].b=0;            t[n_t].a_n=u_i;            ed[n_ed][0]=nn-1;            ed[n_ed][1]=(int)a;            ed[n_ed][2]=n_t;            n_ed++;            n_t++;        }        a++;        }         nn++;    }    for(i=0;i<n_t;i++){            t[i].c=t[i].a[i];            printf("用 %c  代表 %s\n",t[i].c,t[i].a);    }        for(i=0;i<n_ed;i++)        {            printf("%c-%c-%c\n",t[ed[i][0]].c,ed[i][1],t[ed[i][2]].c);        }}void closure(int nn){    int i,j,k;    int ii,jj;    for(i=0;i<t[nn].a_n;i++)        for(j=0;j<n;j++)        {            if(t[nn].a[i]==nfa[j][0])                if(nfa[j][1]=='*')            {                int b=0;                for(ii=0;ii<t[nn].a_n;ii++)                {                    if(t[nn].a[ii]==nfa[j][2])                        b=1;                }                if(b==0)                {                t[nn].a[t[nn].a_n]=nfa[j][2];                t[nn].a_n++;                }            }        }        t[nn].a[t[nn].a_n]='\0';}


2 0
原创粉丝点击